mirror of
https://github.com/pomerium/pomerium.git
synced 2025-05-31 09:57:17 +02:00
very bad demo code
This commit is contained in:
parent
b4aa275403
commit
d588135b3a
30 changed files with 1308 additions and 248 deletions
2
Makefile
2
Makefile
|
@ -40,7 +40,7 @@ all: clean build-deps test lint build ## Runs a clean, build, fmt, lint, test, a
|
||||||
.PHONY: get-envoy
|
.PHONY: get-envoy
|
||||||
get-envoy: ## Fetch envoy binaries
|
get-envoy: ## Fetch envoy binaries
|
||||||
@echo "==> $@"
|
@echo "==> $@"
|
||||||
@cd pkg/envoy/files && env -u GOOS go run ../get-envoy
|
# @cd pkg/envoy/files && env -u GOOS go run ../get-envoy
|
||||||
|
|
||||||
.PHONY: deps-build
|
.PHONY: deps-build
|
||||||
deps-build: get-envoy ## Install build dependencies
|
deps-build: get-envoy ## Install build dependencies
|
||||||
|
|
|
@ -649,7 +649,7 @@ func (a *Authenticate) DeviceAuthLogin(w http.ResponseWriter, r *http.Request) e
|
||||||
fmt.Fprintf(w, `{"token": "%s"}`, string(tokenJwt))
|
fmt.Fprintf(w, `{"token": "%s"}`, string(tokenJwt))
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
authResp, err := authenticator.DeviceAuth(w, r)
|
authResp, err := authenticator.DeviceAuth(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return httputil.NewError(http.StatusInternalServerError,
|
return httputil.NewError(http.StatusInternalServerError,
|
||||||
fmt.Errorf("failed to get device code: %w", err))
|
fmt.Errorf("failed to get device code: %w", err))
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
@ -36,6 +37,9 @@ type Authorize struct {
|
||||||
|
|
||||||
tracerProvider oteltrace.TracerProvider
|
tracerProvider oteltrace.TracerProvider
|
||||||
tracer oteltrace.Tracer
|
tracer oteltrace.Tracer
|
||||||
|
|
||||||
|
activeStreamsMu sync.Mutex
|
||||||
|
activeStreams []chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
// New validates and creates a new Authorize service from a set of config options.
|
// New validates and creates a new Authorize service from a set of config options.
|
||||||
|
@ -48,6 +52,7 @@ func New(ctx context.Context, cfg *config.Config) (*Authorize, error) {
|
||||||
globalCache: storage.NewGlobalCache(time.Minute),
|
globalCache: storage.NewGlobalCache(time.Minute),
|
||||||
tracerProvider: tracerProvider,
|
tracerProvider: tracerProvider,
|
||||||
tracer: tracer,
|
tracer: tracer,
|
||||||
|
activeStreams: []chan error{},
|
||||||
}
|
}
|
||||||
a.accessTracker = NewAccessTracker(a, accessTrackerMaxSize, accessTrackerDebouncePeriod)
|
a.accessTracker = NewAccessTracker(a, accessTrackerMaxSize, accessTrackerDebouncePeriod)
|
||||||
|
|
||||||
|
@ -154,6 +159,15 @@ func newPolicyEvaluator(
|
||||||
|
|
||||||
// OnConfigChange updates internal structures based on config.Options
|
// OnConfigChange updates internal structures based on config.Options
|
||||||
func (a *Authorize) OnConfigChange(ctx context.Context, cfg *config.Config) {
|
func (a *Authorize) OnConfigChange(ctx context.Context, cfg *config.Config) {
|
||||||
|
a.activeStreamsMu.Lock()
|
||||||
|
// demo code
|
||||||
|
if cfg.Options.Routes[0].AllowAnyAuthenticatedUser == false {
|
||||||
|
for _, s := range a.activeStreams {
|
||||||
|
s <- fmt.Errorf("no longer authorized")
|
||||||
|
}
|
||||||
|
clear(a.activeStreams)
|
||||||
|
}
|
||||||
|
a.activeStreamsMu.Unlock()
|
||||||
currentState := a.state.Load()
|
currentState := a.state.Load()
|
||||||
a.currentOptions.Store(cfg.Options)
|
a.currentOptions.Store(cfg.Options)
|
||||||
if newState, err := newAuthorizeStateFromConfig(ctx, a.tracerProvider, cfg, a.store, currentState.evaluator); err != nil {
|
if newState, err := newAuthorizeStateFromConfig(ctx, a.tracerProvider, cfg, a.store, currentState.evaluator); err != nil {
|
||||||
|
|
|
@ -9,13 +9,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
envoy_service_auth_v3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
envoy_service_auth_v3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
"google.golang.org/protobuf/types/known/structpb"
|
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/authorize/evaluator"
|
"github.com/pomerium/pomerium/authorize/evaluator"
|
||||||
"github.com/pomerium/pomerium/config"
|
"github.com/pomerium/pomerium/config"
|
||||||
"github.com/pomerium/pomerium/config/envoyconfig"
|
"github.com/pomerium/pomerium/config/envoyconfig"
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/internal/httputil"
|
"github.com/pomerium/pomerium/internal/httputil"
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
"github.com/pomerium/pomerium/internal/sessions"
|
"github.com/pomerium/pomerium/internal/sessions"
|
||||||
|
@ -24,6 +21,9 @@ import (
|
||||||
"github.com/pomerium/pomerium/pkg/grpc/user"
|
"github.com/pomerium/pomerium/pkg/grpc/user"
|
||||||
"github.com/pomerium/pomerium/pkg/storage"
|
"github.com/pomerium/pomerium/pkg/storage"
|
||||||
"github.com/pomerium/pomerium/pkg/telemetry/requestid"
|
"github.com/pomerium/pomerium/pkg/telemetry/requestid"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
"google.golang.org/protobuf/types/known/structpb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check implements the envoy auth server gRPC endpoint.
|
// Check implements the envoy auth server gRPC endpoint.
|
||||||
|
|
685
authorize/ssh_grpc.go
Normal file
685
authorize/ssh_grpc.go
Normal file
|
@ -0,0 +1,685 @@
|
||||||
|
package authorize
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/url"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/charmbracelet/bubbles/list"
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
extensions_ssh "github.com/pomerium/envoy-custom/api/extensions/filters/network/ssh"
|
||||||
|
"github.com/pomerium/pomerium/config"
|
||||||
|
"github.com/pomerium/pomerium/internal/sessions"
|
||||||
|
"github.com/pomerium/pomerium/pkg/identity"
|
||||||
|
"github.com/pomerium/pomerium/pkg/identity/oauth"
|
||||||
|
gossh "golang.org/x/crypto/ssh"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
"google.golang.org/protobuf/types/known/anypb"
|
||||||
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StreamState struct {
|
||||||
|
Username string
|
||||||
|
Hostname string
|
||||||
|
PublicKey []byte
|
||||||
|
MethodsAuthenticated []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Authorize) ManageStream(
|
||||||
|
server extensions_ssh.StreamManagement_ManageStreamServer,
|
||||||
|
) error {
|
||||||
|
recvC := make(chan *extensions_ssh.ClientMessage, 32)
|
||||||
|
sendC := make(chan *extensions_ssh.ServerMessage, 32)
|
||||||
|
eg, ctx := errgroup.WithContext(server.Context())
|
||||||
|
eg.Go(func() error {
|
||||||
|
defer close(recvC)
|
||||||
|
for {
|
||||||
|
req, err := server.Recv()
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
recvC <- req
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
eg.Go(func() error {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil
|
||||||
|
case msg := <-sendC:
|
||||||
|
if err := server.Send(msg); err != nil {
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var state StreamState
|
||||||
|
|
||||||
|
deviceAuthSuccess := &atomic.Bool{}
|
||||||
|
|
||||||
|
errC := make(chan error, 1)
|
||||||
|
a.activeStreamsMu.Lock()
|
||||||
|
a.activeStreams = append(a.activeStreams, errC)
|
||||||
|
a.activeStreamsMu.Unlock()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case err := <-errC:
|
||||||
|
|
||||||
|
return err
|
||||||
|
case req, ok := <-recvC:
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch req := req.Message.(type) {
|
||||||
|
case *extensions_ssh.ClientMessage_Event:
|
||||||
|
switch event := req.Event.Event.(type) {
|
||||||
|
case *extensions_ssh.StreamEvent_DownstreamConnected:
|
||||||
|
fmt.Println("downstream connected")
|
||||||
|
_ = event
|
||||||
|
case nil:
|
||||||
|
}
|
||||||
|
case *extensions_ssh.ClientMessage_AuthRequest:
|
||||||
|
authReq := req.AuthRequest
|
||||||
|
fmt.Println("auth request")
|
||||||
|
if state.Username == "" {
|
||||||
|
state.Username = authReq.Username
|
||||||
|
}
|
||||||
|
if state.Hostname == "" {
|
||||||
|
state.Hostname = authReq.Hostname
|
||||||
|
}
|
||||||
|
switch authReq.AuthMethod {
|
||||||
|
case "publickey":
|
||||||
|
methodReq, _ := authReq.MethodRequest.UnmarshalNew()
|
||||||
|
pubkeyReq, ok := methodReq.(*extensions_ssh.PublicKeyMethodRequest)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("client sent invalid auth request message")
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// validate public key here
|
||||||
|
//
|
||||||
|
|
||||||
|
state.MethodsAuthenticated = append(state.MethodsAuthenticated, "publickey")
|
||||||
|
state.PublicKey = pubkeyReq.PublicKey
|
||||||
|
|
||||||
|
if authReq.Username == "" && authReq.Hostname == "" {
|
||||||
|
pkData, _ := anypb.New(&extensions_ssh.PublicKeyAllowResponse{
|
||||||
|
PublicKey: state.PublicKey,
|
||||||
|
Permissions: &extensions_ssh.Permissions{
|
||||||
|
PermitPortForwarding: true,
|
||||||
|
PermitAgentForwarding: true,
|
||||||
|
PermitX11Forwarding: true,
|
||||||
|
PermitPty: true,
|
||||||
|
PermitUserRc: true,
|
||||||
|
ValidBefore: timestamppb.New(time.Now().Add(-1 * time.Minute)),
|
||||||
|
ValidAfter: timestamppb.New(time.Now().Add(12 * time.Hour)),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
resp := extensions_ssh.ServerMessage{
|
||||||
|
Message: &extensions_ssh.ServerMessage_AuthResponse{
|
||||||
|
AuthResponse: &extensions_ssh.AuthenticationResponse{
|
||||||
|
Response: &extensions_ssh.AuthenticationResponse_Allow{
|
||||||
|
Allow: &extensions_ssh.AllowResponse{
|
||||||
|
Username: state.Username,
|
||||||
|
Hostname: state.Hostname,
|
||||||
|
AllowedMethods: []*extensions_ssh.AllowedMethod{
|
||||||
|
{
|
||||||
|
Method: "publickey",
|
||||||
|
MethodData: pkData,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Target: extensions_ssh.Target_Internal,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
sendC <- &resp
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !slices.Contains(state.MethodsAuthenticated, "keyboard-interactive") {
|
||||||
|
resp := extensions_ssh.ServerMessage{
|
||||||
|
Message: &extensions_ssh.ServerMessage_AuthResponse{
|
||||||
|
AuthResponse: &extensions_ssh.AuthenticationResponse{
|
||||||
|
Response: &extensions_ssh.AuthenticationResponse_Deny{
|
||||||
|
Deny: &extensions_ssh.DenyResponse{
|
||||||
|
Partial: true,
|
||||||
|
Methods: []string{"keyboard-interactive"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
sendC <- &resp
|
||||||
|
}
|
||||||
|
case "keyboard-interactive":
|
||||||
|
opts := a.currentOptions.Load()
|
||||||
|
var route *config.Policy
|
||||||
|
for r := range opts.GetAllPolicies() {
|
||||||
|
if r.From == "ssh://"+strings.TrimSuffix(strings.Join([]string{state.Hostname, opts.SSHHostname}, "."), ".") {
|
||||||
|
route = r
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if route == nil {
|
||||||
|
return fmt.Errorf("invalid route")
|
||||||
|
}
|
||||||
|
// sessionState := a.state.Load()
|
||||||
|
|
||||||
|
idp, err := opts.GetIdentityProviderForPolicy(route)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
authenticator, err := identity.NewAuthenticator(ctx, a.tracerProvider, oauth.Options{
|
||||||
|
RedirectURL: &url.URL{},
|
||||||
|
ProviderName: idp.GetType(),
|
||||||
|
ProviderURL: idp.GetUrl(),
|
||||||
|
ClientID: idp.GetClientId(),
|
||||||
|
ClientSecret: idp.GetClientSecret(),
|
||||||
|
Scopes: idp.GetScopes(),
|
||||||
|
AuthCodeOptions: idp.GetRequestParams(),
|
||||||
|
DeviceAuthClientType: idp.GetDeviceAuthClientType(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
deviceAuthResp, err := authenticator.DeviceAuth(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
infoReq := extensions_ssh.KeyboardInteractiveInfoPrompts{
|
||||||
|
Name: "Sign in with " + idp.GetType(),
|
||||||
|
Instruction: deviceAuthResp.VerificationURIComplete,
|
||||||
|
Prompts: []*extensions_ssh.KeyboardInteractiveInfoPrompts_Prompt{
|
||||||
|
{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
infoReqAny, _ := anypb.New(&infoReq)
|
||||||
|
resp := extensions_ssh.ServerMessage{
|
||||||
|
Message: &extensions_ssh.ServerMessage_AuthResponse{
|
||||||
|
AuthResponse: &extensions_ssh.AuthenticationResponse{
|
||||||
|
Response: &extensions_ssh.AuthenticationResponse_InfoRequest{
|
||||||
|
InfoRequest: &extensions_ssh.InfoRequest{
|
||||||
|
Method: "keyboard-interactive",
|
||||||
|
Request: infoReqAny,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
sendC <- &resp
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
var claims identity.SessionClaims
|
||||||
|
|
||||||
|
token, err := authenticator.DeviceAccessToken(ctx, deviceAuthResp, &claims)
|
||||||
|
if err != nil {
|
||||||
|
errC <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s := sessions.NewState(idp.Id)
|
||||||
|
err = claims.Claims.Claims(&s)
|
||||||
|
if err != nil {
|
||||||
|
errC <- fmt.Errorf("error unmarshaling session state: %w", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(token)
|
||||||
|
deviceAuthSuccess.Store(true)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
case *extensions_ssh.ClientMessage_InfoResponse:
|
||||||
|
resp := req.InfoResponse
|
||||||
|
if resp.Method == "keyboard-interactive" {
|
||||||
|
r, _ := resp.Response.UnmarshalNew()
|
||||||
|
respInfo, ok := r.(*extensions_ssh.KeyboardInteractiveInfoPromptResponses)
|
||||||
|
if ok {
|
||||||
|
fmt.Println(respInfo.Responses)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if deviceAuthSuccess.Load() {
|
||||||
|
state.MethodsAuthenticated = append(state.MethodsAuthenticated, "keyboard-interactive")
|
||||||
|
} else {
|
||||||
|
retryReq := extensions_ssh.KeyboardInteractiveInfoPrompts{
|
||||||
|
Name: "",
|
||||||
|
Instruction: "Login not successful yet, try again",
|
||||||
|
Prompts: []*extensions_ssh.KeyboardInteractiveInfoPrompts_Prompt{
|
||||||
|
{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
infoReqAny, _ := anypb.New(&retryReq)
|
||||||
|
|
||||||
|
resp := extensions_ssh.ServerMessage{
|
||||||
|
Message: &extensions_ssh.ServerMessage_AuthResponse{
|
||||||
|
AuthResponse: &extensions_ssh.AuthenticationResponse{
|
||||||
|
Response: &extensions_ssh.AuthenticationResponse_InfoRequest{
|
||||||
|
InfoRequest: &extensions_ssh.InfoRequest{
|
||||||
|
Method: "keyboard-interactive",
|
||||||
|
Request: infoReqAny,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
sendC <- &resp
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if slices.Contains(state.MethodsAuthenticated, "publickey") {
|
||||||
|
pkData, _ := anypb.New(&extensions_ssh.PublicKeyAllowResponse{
|
||||||
|
PublicKey: state.PublicKey,
|
||||||
|
Permissions: &extensions_ssh.Permissions{
|
||||||
|
PermitPortForwarding: true,
|
||||||
|
PermitAgentForwarding: true,
|
||||||
|
PermitX11Forwarding: true,
|
||||||
|
PermitPty: true,
|
||||||
|
PermitUserRc: true,
|
||||||
|
ValidBefore: timestamppb.New(time.Now().Add(-1 * time.Minute)),
|
||||||
|
ValidAfter: timestamppb.New(time.Now().Add(12 * time.Hour)),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
authResponse := extensions_ssh.ServerMessage{
|
||||||
|
Message: &extensions_ssh.ServerMessage_AuthResponse{
|
||||||
|
AuthResponse: &extensions_ssh.AuthenticationResponse{
|
||||||
|
Response: &extensions_ssh.AuthenticationResponse_Allow{
|
||||||
|
Allow: &extensions_ssh.AllowResponse{
|
||||||
|
Username: state.Username,
|
||||||
|
Hostname: state.Hostname,
|
||||||
|
AllowedMethods: []*extensions_ssh.AllowedMethod{
|
||||||
|
{
|
||||||
|
Method: "publickey",
|
||||||
|
MethodData: pkData,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: "keyboard-interactive",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Target: extensions_ssh.Target_Upstream,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
sendC <- &authResponse
|
||||||
|
} else {
|
||||||
|
resp := extensions_ssh.ServerMessage{
|
||||||
|
Message: &extensions_ssh.ServerMessage_AuthResponse{
|
||||||
|
AuthResponse: &extensions_ssh.AuthenticationResponse{
|
||||||
|
Response: &extensions_ssh.AuthenticationResponse_Deny{
|
||||||
|
Deny: &extensions_ssh.DenyResponse{
|
||||||
|
Partial: true,
|
||||||
|
Methods: []string{"publickey"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
sendC <- &resp
|
||||||
|
}
|
||||||
|
|
||||||
|
case nil:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// See RFC 4254, section 5.1.
|
||||||
|
const msgChannelOpen = 90
|
||||||
|
|
||||||
|
type channelOpenMsg struct {
|
||||||
|
ChanType string `sshtype:"90"`
|
||||||
|
PeersID uint32
|
||||||
|
PeersWindow uint32
|
||||||
|
MaxPacketSize uint32
|
||||||
|
TypeSpecificData []byte `ssh:"rest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
msgChannelExtendedData = 95
|
||||||
|
msgChannelData = 94
|
||||||
|
)
|
||||||
|
|
||||||
|
// Used for debug print outs of packets.
|
||||||
|
type channelDataMsg struct {
|
||||||
|
PeersID uint32 `sshtype:"94"`
|
||||||
|
Length uint32
|
||||||
|
Rest []byte `ssh:"rest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// See RFC 4254, section 5.1.
|
||||||
|
const msgChannelOpenConfirm = 91
|
||||||
|
|
||||||
|
type channelOpenConfirmMsg struct {
|
||||||
|
PeersID uint32 `sshtype:"91"`
|
||||||
|
MyID uint32
|
||||||
|
MyWindow uint32
|
||||||
|
MaxPacketSize uint32
|
||||||
|
TypeSpecificData []byte `ssh:"rest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const msgChannelRequest = 98
|
||||||
|
|
||||||
|
type channelRequestMsg struct {
|
||||||
|
PeersID uint32 `sshtype:"98"`
|
||||||
|
Request string
|
||||||
|
WantReply bool
|
||||||
|
RequestSpecificData []byte `ssh:"rest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// See RFC 4254, section 5.4.
|
||||||
|
const msgChannelSuccess = 99
|
||||||
|
|
||||||
|
type channelRequestSuccessMsg struct {
|
||||||
|
PeersID uint32 `sshtype:"99"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// See RFC 4254, section 5.4.
|
||||||
|
const msgChannelFailure = 100
|
||||||
|
|
||||||
|
type channelRequestFailureMsg struct {
|
||||||
|
PeersID uint32 `sshtype:"100"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// See RFC 4254, section 5.3
|
||||||
|
const msgChannelClose = 97
|
||||||
|
|
||||||
|
type channelCloseMsg struct {
|
||||||
|
PeersID uint32 `sshtype:"97"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// See RFC 4254, section 5.3
|
||||||
|
const msgChannelEOF = 96
|
||||||
|
|
||||||
|
type channelEOFMsg struct {
|
||||||
|
PeersID uint32 `sshtype:"96"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Authorize) ServeChannel(
|
||||||
|
server extensions_ssh.StreamManagement_ServeChannelServer,
|
||||||
|
) error {
|
||||||
|
var program *tea.Program
|
||||||
|
inputR, inputW := io.Pipe()
|
||||||
|
outputR, outputW := io.Pipe()
|
||||||
|
var peerId uint32
|
||||||
|
|
||||||
|
var downstreamChannelInfo *extensions_ssh.SSHDownstreamChannelInfo
|
||||||
|
var downstreamPtyInfo *extensions_ssh.SSHDownstreamPTYInfo
|
||||||
|
for {
|
||||||
|
channelMsg, err := server.Recv()
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rawMsg := channelMsg.GetRawBytes().GetValue()
|
||||||
|
switch rawMsg[0] {
|
||||||
|
case msgChannelOpen:
|
||||||
|
var msg channelOpenMsg
|
||||||
|
gossh.Unmarshal(rawMsg, &msg)
|
||||||
|
|
||||||
|
var confirm channelOpenConfirmMsg
|
||||||
|
peerId = msg.PeersID
|
||||||
|
confirm.PeersID = peerId
|
||||||
|
confirm.MyID = 1
|
||||||
|
confirm.MyWindow = msg.PeersWindow
|
||||||
|
confirm.MaxPacketSize = msg.MaxPacketSize
|
||||||
|
downstreamChannelInfo = &extensions_ssh.SSHDownstreamChannelInfo{
|
||||||
|
ChannelType: msg.ChanType,
|
||||||
|
DownstreamChannelId: confirm.PeersID,
|
||||||
|
InternalUpstreamChannelId: confirm.MyID,
|
||||||
|
InitialWindowSize: confirm.MyWindow,
|
||||||
|
MaxPacketSize: confirm.MaxPacketSize,
|
||||||
|
}
|
||||||
|
if err := server.Send(&extensions_ssh.ChannelMessage{
|
||||||
|
Message: &extensions_ssh.ChannelMessage_RawBytes{
|
||||||
|
RawBytes: &wrapperspb.BytesValue{
|
||||||
|
Value: gossh.Marshal(confirm),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case msgChannelRequest:
|
||||||
|
var msg channelRequestMsg
|
||||||
|
gossh.Unmarshal(rawMsg, &msg)
|
||||||
|
|
||||||
|
switch msg.Request {
|
||||||
|
case "pty-req":
|
||||||
|
req := parsePtyReq(msg.RequestSpecificData)
|
||||||
|
items := []list.Item{
|
||||||
|
item("ubuntu@vm"),
|
||||||
|
item("joe@local"),
|
||||||
|
}
|
||||||
|
downstreamPtyInfo = &extensions_ssh.SSHDownstreamPTYInfo{
|
||||||
|
TermEnv: req.TermEnv,
|
||||||
|
WidthColumns: req.Width,
|
||||||
|
HeightRows: req.Height,
|
||||||
|
WidthPx: req.WidthPx,
|
||||||
|
HeightPx: req.HeightPx,
|
||||||
|
Modes: req.Modes,
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultWidth = 20
|
||||||
|
|
||||||
|
l := list.New(items, itemDelegate{}, defaultWidth, listHeight)
|
||||||
|
l.Title = "Connect to which server?"
|
||||||
|
l.SetShowStatusBar(false)
|
||||||
|
l.SetFilteringEnabled(false)
|
||||||
|
l.Styles.Title = titleStyle
|
||||||
|
l.Styles.PaginationStyle = paginationStyle
|
||||||
|
l.Styles.HelpStyle = helpStyle
|
||||||
|
|
||||||
|
program = tea.NewProgram(model{list: l},
|
||||||
|
tea.WithInput(inputR),
|
||||||
|
tea.WithOutput(outputW),
|
||||||
|
tea.WithAltScreen(),
|
||||||
|
tea.WithContext(server.Context()),
|
||||||
|
tea.WithEnvironment([]string{"TERM=" + req.TermEnv}),
|
||||||
|
)
|
||||||
|
go func() {
|
||||||
|
answer, err := program.Run()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
username, hostname, _ := strings.Cut(answer.(model).choice, "@")
|
||||||
|
handOff, _ := anypb.New(&extensions_ssh.SSHChannelControlAction{
|
||||||
|
Action: &extensions_ssh.SSHChannelControlAction_HandOff{
|
||||||
|
HandOff: &extensions_ssh.SSHChannelControlAction_HandOffUpstream{
|
||||||
|
DownstreamChannelInfo: downstreamChannelInfo,
|
||||||
|
DownstreamPtyInfo: downstreamPtyInfo,
|
||||||
|
UpstreamAuth: &extensions_ssh.AllowResponse{
|
||||||
|
Username: username,
|
||||||
|
Hostname: hostname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := server.Send(&extensions_ssh.ChannelMessage{
|
||||||
|
Message: &extensions_ssh.ChannelMessage_ChannelControl{
|
||||||
|
ChannelControl: &extensions_ssh.ChannelControl{
|
||||||
|
Protocol: "ssh",
|
||||||
|
ControlAction: handOff,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
var buf [4096]byte
|
||||||
|
for {
|
||||||
|
n, err := outputR.Read(buf[:])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := server.Send(&extensions_ssh.ChannelMessage{
|
||||||
|
Message: &extensions_ssh.ChannelMessage_RawBytes{
|
||||||
|
RawBytes: &wrapperspb.BytesValue{
|
||||||
|
Value: gossh.Marshal(channelDataMsg{
|
||||||
|
PeersID: peerId,
|
||||||
|
Length: uint32(n),
|
||||||
|
Rest: buf[:n],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
program.Send(tea.WindowSizeMsg{Width: int(req.Width), Height: int(req.Height)})
|
||||||
|
|
||||||
|
if err := server.Send(&extensions_ssh.ChannelMessage{
|
||||||
|
Message: &extensions_ssh.ChannelMessage_RawBytes{
|
||||||
|
RawBytes: &wrapperspb.BytesValue{
|
||||||
|
Value: gossh.Marshal(channelRequestSuccessMsg{
|
||||||
|
PeersID: peerId,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case msgChannelData:
|
||||||
|
var msg channelDataMsg
|
||||||
|
gossh.Unmarshal(rawMsg, &msg)
|
||||||
|
|
||||||
|
if program != nil {
|
||||||
|
inputW.Write(msg.Rest)
|
||||||
|
}
|
||||||
|
case msgChannelClose:
|
||||||
|
var msg channelDataMsg
|
||||||
|
gossh.Unmarshal(rawMsg, &msg)
|
||||||
|
default:
|
||||||
|
panic("unhandled message: " + fmt.Sprint(rawMsg[1]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ptyReq struct {
|
||||||
|
TermEnv string
|
||||||
|
Width, Height uint32
|
||||||
|
WidthPx, HeightPx uint32
|
||||||
|
Modes []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func parsePtyReq(reqData []byte) ptyReq {
|
||||||
|
termEnvLen := binary.BigEndian.Uint32(reqData)
|
||||||
|
reqData = reqData[4:]
|
||||||
|
termEnv := string(reqData[:termEnvLen])
|
||||||
|
reqData = reqData[termEnvLen:]
|
||||||
|
return ptyReq{
|
||||||
|
TermEnv: termEnv,
|
||||||
|
Width: binary.BigEndian.Uint32(reqData),
|
||||||
|
Height: binary.BigEndian.Uint32(reqData[4:]),
|
||||||
|
WidthPx: binary.BigEndian.Uint32(reqData[8:]),
|
||||||
|
HeightPx: binary.BigEndian.Uint32(reqData[12:]),
|
||||||
|
Modes: reqData[16:],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const listHeight = 14
|
||||||
|
|
||||||
|
var (
|
||||||
|
titleStyle = lipgloss.NewStyle().MarginLeft(2)
|
||||||
|
itemStyle = lipgloss.NewStyle().PaddingLeft(4)
|
||||||
|
selectedItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("170"))
|
||||||
|
paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4)
|
||||||
|
helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1)
|
||||||
|
quitTextStyle = lipgloss.NewStyle().Margin(1, 0, 2, 4)
|
||||||
|
)
|
||||||
|
|
||||||
|
type item string
|
||||||
|
|
||||||
|
func (i item) FilterValue() string { return "" }
|
||||||
|
|
||||||
|
type itemDelegate struct{}
|
||||||
|
|
||||||
|
func (d itemDelegate) Height() int { return 1 }
|
||||||
|
func (d itemDelegate) Spacing() int { return 0 }
|
||||||
|
func (d itemDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil }
|
||||||
|
func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) {
|
||||||
|
i, ok := listItem.(item)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
str := fmt.Sprintf("%d. %s", index+1, i)
|
||||||
|
|
||||||
|
fn := itemStyle.Render
|
||||||
|
if index == m.Index() {
|
||||||
|
fn = func(s ...string) string {
|
||||||
|
return selectedItemStyle.Render("> " + strings.Join(s, " "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(w, fn(str))
|
||||||
|
}
|
||||||
|
|
||||||
|
type model struct {
|
||||||
|
list list.Model
|
||||||
|
choice string
|
||||||
|
quitting bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m model) Init() tea.Cmd {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
case tea.WindowSizeMsg:
|
||||||
|
m.list.SetWidth(msg.Width)
|
||||||
|
return m, nil
|
||||||
|
|
||||||
|
case tea.KeyMsg:
|
||||||
|
switch keypress := msg.String(); keypress {
|
||||||
|
case "q", "ctrl+c":
|
||||||
|
m.quitting = true
|
||||||
|
return m, tea.Quit
|
||||||
|
|
||||||
|
case "enter":
|
||||||
|
i, ok := m.list.SelectedItem().(item)
|
||||||
|
if ok {
|
||||||
|
m.choice = string(i)
|
||||||
|
}
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmd tea.Cmd
|
||||||
|
m.list, cmd = m.list.Update(msg)
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m model) View() string {
|
||||||
|
if m.choice != "" {
|
||||||
|
return quitTextStyle.Render(fmt.Sprintf("%s? Sounds good to me.", m.choice))
|
||||||
|
}
|
||||||
|
if m.quitting {
|
||||||
|
return quitTextStyle.Render("Not hungry? That’s cool.")
|
||||||
|
}
|
||||||
|
return "\n" + m.list.View()
|
||||||
|
}
|
|
@ -65,6 +65,14 @@ func (b *Builder) BuildListeners(
|
||||||
listeners = append(listeners, li)
|
listeners = append(listeners, li)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if shouldStartSSHListener(cfg.Options) {
|
||||||
|
li, err := b.buildSSHListener(ctx, cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
listeners = append(listeners, li)
|
||||||
|
}
|
||||||
|
|
||||||
li, err := b.buildOutboundListener(cfg)
|
li, err := b.buildOutboundListener(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -121,3 +121,10 @@ func shouldStartGRPCListener(options *config.Options) bool {
|
||||||
|
|
||||||
return config.IsAuthorize(options.Services) || config.IsDataBroker(options.Services)
|
return config.IsAuthorize(options.Services) || config.IsDataBroker(options.Services)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shouldStartSSHListener(options *config.Options) bool {
|
||||||
|
if options.SSHAddr == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return config.IsProxy(options.Services)
|
||||||
|
}
|
||||||
|
|
168
config/envoyconfig/listeners_ssh.go
Normal file
168
config/envoyconfig/listeners_ssh.go
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
package envoyconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
xds_core_v3 "github.com/cncf/xds/go/xds/core/v3"
|
||||||
|
xds_matcher_v3 "github.com/cncf/xds/go/xds/type/matcher/v3"
|
||||||
|
envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
||||||
|
envoy_config_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
|
||||||
|
envoy_generic_proxy_action_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/generic_proxy/action/v3"
|
||||||
|
envoy_generic_proxy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/generic_proxy/matcher/v3"
|
||||||
|
envoy_generic_router_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/generic_proxy/router/v3"
|
||||||
|
envoy_generic_proxy_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/generic_proxy/v3"
|
||||||
|
matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
|
||||||
|
extensions_ssh "github.com/pomerium/envoy-custom/api/extensions/filters/network/ssh"
|
||||||
|
"github.com/pomerium/pomerium/config"
|
||||||
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (b *Builder) buildSSHListener(ctx context.Context, cfg *config.Config) (*envoy_config_listener_v3.Listener, error) {
|
||||||
|
rc, err := b.buildRouteConfig(ctx, cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var sshHostKeys []*extensions_ssh.HostKeyPair
|
||||||
|
for _, hk := range cfg.Options.SSHHostKeys {
|
||||||
|
sshHostKeys = append(sshHostKeys, &extensions_ssh.HostKeyPair{
|
||||||
|
PublicKeyFile: hk.PublicKeyFile,
|
||||||
|
PrivateKeyFile: hk.PrivateKeyFile,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
var grpcClientTimeout *durationpb.Duration
|
||||||
|
if cfg.Options.GRPCClientTimeout != 0 {
|
||||||
|
grpcClientTimeout = durationpb.New(cfg.Options.GRPCClientTimeout)
|
||||||
|
} else {
|
||||||
|
grpcClientTimeout = durationpb.New(30 * time.Second)
|
||||||
|
}
|
||||||
|
li := &envoy_config_listener_v3.Listener{
|
||||||
|
Name: "ssh",
|
||||||
|
Address: buildTCPAddress(cfg.Options.SSHAddr, 22),
|
||||||
|
FilterChains: []*envoy_config_listener_v3.FilterChain{
|
||||||
|
{
|
||||||
|
Filters: []*envoy_config_listener_v3.Filter{
|
||||||
|
{
|
||||||
|
Name: "generic_proxy",
|
||||||
|
ConfigType: &envoy_config_listener_v3.Filter_TypedConfig{
|
||||||
|
TypedConfig: marshalAny(&envoy_generic_proxy_v3.GenericProxy{
|
||||||
|
StatPrefix: "ssh",
|
||||||
|
CodecConfig: &envoy_config_core_v3.TypedExtensionConfig{
|
||||||
|
Name: "envoy.generic_proxy.codecs.ssh",
|
||||||
|
TypedConfig: marshalAny(&extensions_ssh.CodecConfig{
|
||||||
|
HostKeys: sshHostKeys,
|
||||||
|
UserCaKey: &extensions_ssh.HostKeyPair{
|
||||||
|
PublicKeyFile: cfg.Options.SSHUserCAKey.PublicKeyFile,
|
||||||
|
PrivateKeyFile: cfg.Options.SSHUserCAKey.PrivateKeyFile,
|
||||||
|
},
|
||||||
|
GrpcService: &envoy_config_core_v3.GrpcService{
|
||||||
|
Timeout: grpcClientTimeout,
|
||||||
|
TargetSpecifier: &envoy_config_core_v3.GrpcService_EnvoyGrpc_{
|
||||||
|
EnvoyGrpc: &envoy_config_core_v3.GrpcService_EnvoyGrpc{
|
||||||
|
ClusterName: "pomerium-authorize",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
Filters: []*envoy_config_core_v3.TypedExtensionConfig{
|
||||||
|
{
|
||||||
|
Name: "envoy.filters.generic.router",
|
||||||
|
TypedConfig: marshalAny(&envoy_generic_router_v3.Router{
|
||||||
|
BindUpstreamConnection: true,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RouteSpecifier: &envoy_generic_proxy_v3.GenericProxy_RouteConfig{
|
||||||
|
RouteConfig: rc,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return li, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Builder) buildRouteConfig(_ context.Context, cfg *config.Config) (*envoy_generic_proxy_v3.RouteConfiguration, error) {
|
||||||
|
routeMatchers := []*xds_matcher_v3.Matcher_MatcherList_FieldMatcher{}
|
||||||
|
for route := range cfg.Options.GetAllPolicies() {
|
||||||
|
from, err := url.Parse(route.From)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if from.Scheme != "ssh" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fromHost := from.Hostname()
|
||||||
|
if cfg.Options.SSHHostname != "" {
|
||||||
|
suffix := "." + cfg.Options.SSHHostname
|
||||||
|
fromHost = strings.TrimSuffix(fromHost, suffix)
|
||||||
|
}
|
||||||
|
if len(route.To) > 1 {
|
||||||
|
return nil, fmt.Errorf("only one 'to' entry allowed for ssh routes")
|
||||||
|
}
|
||||||
|
to := route.To[0].URL
|
||||||
|
if to.Scheme != "ssh" {
|
||||||
|
return nil, fmt.Errorf("'to' route url must have ssh scheme")
|
||||||
|
}
|
||||||
|
clusterId := getClusterID(route)
|
||||||
|
routeMatchers = append(routeMatchers, &xds_matcher_v3.Matcher_MatcherList_FieldMatcher{
|
||||||
|
Predicate: &xds_matcher_v3.Matcher_MatcherList_Predicate{
|
||||||
|
MatchType: &xds_matcher_v3.Matcher_MatcherList_Predicate_SinglePredicate_{
|
||||||
|
SinglePredicate: &xds_matcher_v3.Matcher_MatcherList_Predicate_SinglePredicate{
|
||||||
|
Input: &xds_core_v3.TypedExtensionConfig{
|
||||||
|
Name: "request",
|
||||||
|
TypedConfig: marshalAny(&envoy_generic_proxy_matcher_v3.RequestMatchInput{}),
|
||||||
|
},
|
||||||
|
Matcher: &xds_matcher_v3.Matcher_MatcherList_Predicate_SinglePredicate_CustomMatch{
|
||||||
|
CustomMatch: &xds_core_v3.TypedExtensionConfig{
|
||||||
|
Name: "request",
|
||||||
|
TypedConfig: marshalAny(&envoy_generic_proxy_matcher_v3.RequestMatcher{
|
||||||
|
Host: &matcherv3.StringMatcher{
|
||||||
|
MatchPattern: &matcherv3.StringMatcher_Exact{
|
||||||
|
Exact: fromHost,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
OnMatch: &xds_matcher_v3.Matcher_OnMatch{
|
||||||
|
OnMatch: &xds_matcher_v3.Matcher_OnMatch_Action{
|
||||||
|
Action: &xds_core_v3.TypedExtensionConfig{
|
||||||
|
Name: "route",
|
||||||
|
TypedConfig: marshalAny(&envoy_generic_proxy_action_v3.RouteAction{
|
||||||
|
ClusterSpecifier: &envoy_generic_proxy_action_v3.RouteAction_Cluster{
|
||||||
|
Cluster: clusterId,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &envoy_generic_proxy_v3.RouteConfiguration{
|
||||||
|
Name: "route_config",
|
||||||
|
VirtualHosts: []*envoy_generic_proxy_v3.VirtualHost{
|
||||||
|
{
|
||||||
|
Name: "ssh",
|
||||||
|
Hosts: []string{"*"},
|
||||||
|
Routes: &xds_matcher_v3.Matcher{
|
||||||
|
MatcherType: &xds_matcher_v3.Matcher_MatcherList_{
|
||||||
|
MatcherList: &xds_matcher_v3.Matcher_MatcherList{
|
||||||
|
Matchers: routeMatchers,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -214,6 +214,11 @@ func (b *Builder) buildRoutesForPoliciesWithCatchAll(
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
if fromURL.Scheme == "ssh" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if !strings.Contains(fromURL.Host, "*") {
|
if !strings.Contains(fromURL.Host, "*") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,6 +230,11 @@ type Options struct {
|
||||||
|
|
||||||
GRPCClientTimeout time.Duration `mapstructure:"grpc_client_timeout" yaml:"grpc_client_timeout,omitempty"`
|
GRPCClientTimeout time.Duration `mapstructure:"grpc_client_timeout" yaml:"grpc_client_timeout,omitempty"`
|
||||||
|
|
||||||
|
SSHAddr string `mapstructure:"ssh_address" yaml:"ssh_address,omitempty"`
|
||||||
|
SSHHostname string `mapstructure:"ssh_hostname" yaml:"ssh_hostname,omitempty"`
|
||||||
|
SSHHostKeys []SSHKeyPair `mapstructure:"ssh_host_keys" yaml:"ssh_host_keys,omitempty"`
|
||||||
|
SSHUserCAKey SSHKeyPair `mapstructure:"ssh_user_ca_key" yaml:"ssh_user_ca_key,omitempty"`
|
||||||
|
|
||||||
// DataBrokerURLString is the routable destination of the databroker service's gRPC endpoint.
|
// DataBrokerURLString is the routable destination of the databroker service's gRPC endpoint.
|
||||||
DataBrokerURLString string `mapstructure:"databroker_service_url" yaml:"databroker_service_url,omitempty"`
|
DataBrokerURLString string `mapstructure:"databroker_service_url" yaml:"databroker_service_url,omitempty"`
|
||||||
DataBrokerURLStrings []string `mapstructure:"databroker_service_urls" yaml:"databroker_service_urls,omitempty"`
|
DataBrokerURLStrings []string `mapstructure:"databroker_service_urls" yaml:"databroker_service_urls,omitempty"`
|
||||||
|
@ -290,6 +295,11 @@ type certificateFilePair struct {
|
||||||
KeyFile string `mapstructure:"key" yaml:"key,omitempty"`
|
KeyFile string `mapstructure:"key" yaml:"key,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SSHKeyPair struct {
|
||||||
|
PublicKeyFile string `mapstructure:"public_key_file" yaml:"public_key_file,omitempty"`
|
||||||
|
PrivateKeyFile string `mapstructure:"private_key_file" yaml:"private_key_file,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// DefaultOptions are the default configuration options for pomerium
|
// DefaultOptions are the default configuration options for pomerium
|
||||||
var defaultOptions = Options{
|
var defaultOptions = Options{
|
||||||
LogLevel: LogLevelInfo,
|
LogLevel: LogLevelInfo,
|
||||||
|
@ -1298,6 +1308,11 @@ func (o *Options) GetAllRouteableHTTPHosts() ([]string, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
if fromURL.Scheme == "ssh" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
hosts.InsertSlice(urlutil.GetDomainsForURL(fromURL, !o.IsRuntimeFlagSet(RuntimeFlagMatchAnyIncomingPort)))
|
hosts.InsertSlice(urlutil.GetDomainsForURL(fromURL, !o.IsRuntimeFlagSet(RuntimeFlagMatchAnyIncomingPort)))
|
||||||
if policy.TLSDownstreamServerName != "" {
|
if policy.TLSDownstreamServerName != "" {
|
||||||
tlsURL := fromURL.ResolveReference(&url.URL{Host: policy.TLSDownstreamServerName})
|
tlsURL := fromURL.ResolveReference(&url.URL{Host: policy.TLSDownstreamServerName})
|
||||||
|
|
24
go.mod
24
go.mod
|
@ -13,7 +13,13 @@ require (
|
||||||
github.com/bits-and-blooms/bitset v1.20.0
|
github.com/bits-and-blooms/bitset v1.20.0
|
||||||
github.com/caddyserver/certmagic v0.21.4
|
github.com/caddyserver/certmagic v0.21.4
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0
|
github.com/cenkalti/backoff/v4 v4.3.0
|
||||||
|
github.com/charmbracelet/bubbles v0.20.0
|
||||||
|
github.com/charmbracelet/bubbletea v1.3.3
|
||||||
|
github.com/charmbracelet/lipgloss v1.0.0
|
||||||
|
github.com/charmbracelet/x/ansi v0.8.0
|
||||||
|
github.com/charmbracelet/x/term v0.2.1
|
||||||
github.com/cloudflare/circl v1.5.0
|
github.com/cloudflare/circl v1.5.0
|
||||||
|
github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3
|
||||||
github.com/coreos/go-oidc/v3 v3.11.0
|
github.com/coreos/go-oidc/v3 v3.11.0
|
||||||
github.com/docker/docker v27.4.1+incompatible
|
github.com/docker/docker v27.4.1+incompatible
|
||||||
github.com/envoyproxy/go-control-plane/envoy v1.32.3
|
github.com/envoyproxy/go-control-plane/envoy v1.32.3
|
||||||
|
@ -88,8 +94,8 @@ require (
|
||||||
golang.org/x/crypto v0.31.0
|
golang.org/x/crypto v0.31.0
|
||||||
golang.org/x/net v0.33.0
|
golang.org/x/net v0.33.0
|
||||||
golang.org/x/oauth2 v0.24.0
|
golang.org/x/oauth2 v0.24.0
|
||||||
golang.org/x/sync v0.10.0
|
golang.org/x/sync v0.11.0
|
||||||
golang.org/x/sys v0.28.0
|
golang.org/x/sys v0.30.0
|
||||||
golang.org/x/time v0.8.0
|
golang.org/x/time v0.8.0
|
||||||
google.golang.org/api v0.214.0
|
google.golang.org/api v0.214.0
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576
|
||||||
|
@ -118,6 +124,7 @@ require (
|
||||||
github.com/agnivade/levenshtein v1.2.0 // indirect
|
github.com/agnivade/levenshtein v1.2.0 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
||||||
|
github.com/atotto/clipboard v0.1.4 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.48 // indirect
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.48 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22 // indirect
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22 // indirect
|
||||||
|
@ -133,10 +140,10 @@ require (
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.7 // indirect
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.7 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.3 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.3 // indirect
|
||||||
github.com/aws/smithy-go v1.22.1 // indirect
|
github.com/aws/smithy-go v1.22.1 // indirect
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/caddyserver/zerossl v0.1.3 // indirect
|
github.com/caddyserver/zerossl v0.1.3 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3 // indirect
|
|
||||||
github.com/containerd/log v0.1.0 // indirect
|
github.com/containerd/log v0.1.0 // indirect
|
||||||
github.com/containerd/platforms v0.2.1 // indirect
|
github.com/containerd/platforms v0.2.1 // indirect
|
||||||
github.com/cpuguy83/dockercfg v0.3.2 // indirect
|
github.com/cpuguy83/dockercfg v0.3.2 // indirect
|
||||||
|
@ -146,6 +153,7 @@ require (
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 // indirect
|
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 // indirect
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
|
||||||
|
@ -179,10 +187,13 @@ require (
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||||
github.com/kralicky/go-adaptive-radix-tree v0.0.0-20240624235931-330eb762e74c // indirect
|
github.com/kralicky/go-adaptive-radix-tree v0.0.0-20240624235931-330eb762e74c // indirect
|
||||||
github.com/libdns/libdns v0.2.2 // indirect
|
github.com/libdns/libdns v0.2.2 // indirect
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae // indirect
|
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
github.com/miekg/dns v1.1.62 // indirect
|
github.com/miekg/dns v1.1.62 // indirect
|
||||||
github.com/minio/md5-simd v1.1.2 // indirect
|
github.com/minio/md5-simd v1.1.2 // indirect
|
||||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||||
|
@ -192,6 +203,9 @@ require (
|
||||||
github.com/moby/sys/userns v0.1.0 // indirect
|
github.com/moby/sys/userns v0.1.0 // indirect
|
||||||
github.com/moby/term v0.5.0 // indirect
|
github.com/moby/term v0.5.0 // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||||
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
|
github.com/muesli/termenv v0.15.2 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.19.1 // indirect
|
github.com/onsi/ginkgo/v2 v2.19.1 // indirect
|
||||||
|
@ -206,9 +220,11 @@ require (
|
||||||
github.com/prometheus/statsd_exporter v0.22.7 // indirect
|
github.com/prometheus/statsd_exporter v0.22.7 // indirect
|
||||||
github.com/quic-go/qpack v0.5.1 // indirect
|
github.com/quic-go/qpack v0.5.1 // indirect
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/rs/xid v1.6.0 // indirect
|
github.com/rs/xid v1.6.0 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
|
github.com/sahilm/fuzzy v0.1.1 // indirect
|
||||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
|
@ -246,3 +262,5 @@ require (
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace github.com/pomerium/envoy-custom => ../envoy-custom
|
||||||
|
|
44
go.sum
44
go.sum
|
@ -96,6 +96,8 @@ github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7D
|
||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
||||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
||||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||||
|
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||||
|
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.32.7 h1:ky5o35oENWi0JYWUZkB7WYvVPP+bcRF5/Iq7JWSb5Rw=
|
github.com/aws/aws-sdk-go-v2 v1.32.7 h1:ky5o35oENWi0JYWUZkB7WYvVPP+bcRF5/Iq7JWSb5Rw=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.32.7/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U=
|
github.com/aws/aws-sdk-go-v2 v1.32.7/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U=
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8=
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8=
|
||||||
|
@ -132,6 +134,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.33.3 h1:Xgv/hyNgvLda/M9l9qxXc4UFSgpp
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.3/go.mod h1:5Gn+d+VaaRgsjewpMvGazt0WfcFO+Md4wLOuBfGR9Bc=
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.3/go.mod h1:5Gn+d+VaaRgsjewpMvGazt0WfcFO+Md4wLOuBfGR9Bc=
|
||||||
github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro=
|
github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro=
|
||||||
github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
@ -155,6 +159,16 @@ github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
|
||||||
|
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
|
||||||
|
github.com/charmbracelet/bubbletea v1.3.3 h1:WpU6fCY0J2vDWM3zfS3vIDi/ULq3SYphZhkAGGvmEUY=
|
||||||
|
github.com/charmbracelet/bubbletea v1.3.3/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo=
|
||||||
|
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
|
||||||
|
github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
|
||||||
|
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
|
||||||
|
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
|
||||||
|
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||||
|
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
@ -208,6 +222,8 @@ github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJP
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM=
|
github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM=
|
||||||
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
|
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||||
github.com/exaring/otelpgx v0.8.0 h1:uqoDIW9qKkyz479z2cGrmJ8OJypydyEA+xwey4ukvNo=
|
github.com/exaring/otelpgx v0.8.0 h1:uqoDIW9qKkyz479z2cGrmJ8OJypydyEA+xwey4ukvNo=
|
||||||
github.com/exaring/otelpgx v0.8.0/go.mod h1:ANkRZDfgfmN6yJS1xKMkshbnsHO8at5sYwtVEYOX8hc=
|
github.com/exaring/otelpgx v0.8.0/go.mod h1:ANkRZDfgfmN6yJS1xKMkshbnsHO8at5sYwtVEYOX8hc=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
|
@ -431,6 +447,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
|
||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
|
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
|
||||||
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae h1:dIZY4ULFcto4tAFlj1FYZl8ztUZ13bdq+PLY+NOfbyI=
|
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae h1:dIZY4ULFcto4tAFlj1FYZl8ztUZ13bdq+PLY+NOfbyI=
|
||||||
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
|
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
|
||||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||||
|
@ -443,6 +461,10 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
||||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||||
|
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mholt/acmez/v2 v2.0.3 h1:CgDBlEwg3QBp6s45tPQmFIBrkRIkBT4rW4orMM6p4sw=
|
github.com/mholt/acmez/v2 v2.0.3 h1:CgDBlEwg3QBp6s45tPQmFIBrkRIkBT4rW4orMM6p4sw=
|
||||||
github.com/mholt/acmez/v2 v2.0.3/go.mod h1:pQ1ysaDeGrIMvJ9dfJMk5kJNkn7L2sb3UhyrX6Q91cw=
|
github.com/mholt/acmez/v2 v2.0.3/go.mod h1:pQ1ysaDeGrIMvJ9dfJMk5kJNkn7L2sb3UhyrX6Q91cw=
|
||||||
|
@ -475,6 +497,12 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||||
|
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||||
|
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||||
|
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||||
|
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
@ -524,8 +552,6 @@ github.com/pomerium/csrf v1.7.0 h1:Qp4t6oyEod3svQtKfJZs589mdUTWKVf7q0PgCKYCshY=
|
||||||
github.com/pomerium/csrf v1.7.0/go.mod h1:hAPZV47mEj2T9xFs+ysbum4l7SF1IdrryYaY6PdoIqw=
|
github.com/pomerium/csrf v1.7.0/go.mod h1:hAPZV47mEj2T9xFs+ysbum4l7SF1IdrryYaY6PdoIqw=
|
||||||
github.com/pomerium/datasource v0.18.2-0.20221108160055-c6134b5ed524 h1:3YQY1sb54tEEbr0L73rjHkpLB0IB6qh3zl1+XQbMLis=
|
github.com/pomerium/datasource v0.18.2-0.20221108160055-c6134b5ed524 h1:3YQY1sb54tEEbr0L73rjHkpLB0IB6qh3zl1+XQbMLis=
|
||||||
github.com/pomerium/datasource v0.18.2-0.20221108160055-c6134b5ed524/go.mod h1:7fGbUYJnU8RcxZJvUvhukOIBv1G7LWDAHMfDxAf5+Y0=
|
github.com/pomerium/datasource v0.18.2-0.20221108160055-c6134b5ed524/go.mod h1:7fGbUYJnU8RcxZJvUvhukOIBv1G7LWDAHMfDxAf5+Y0=
|
||||||
github.com/pomerium/envoy-custom v1.32.4-0.20250114182541-6f6d2147bea6 h1:QLVgpx23jcbgR9qJzIicJ+uXGjQXO0GAy55SCo0Jd9o=
|
|
||||||
github.com/pomerium/envoy-custom v1.32.4-0.20250114182541-6f6d2147bea6/go.mod h1:afbaKE6YfshVUOrYc6XWUWfZcXencWmi1jTc00ki0Oo=
|
|
||||||
github.com/pomerium/protoutil v0.0.0-20240813175624-47b7ac43ff46 h1:NRTg8JOXCxcIA1lAgD74iYud0rbshbWOB3Ou4+Huil8=
|
github.com/pomerium/protoutil v0.0.0-20240813175624-47b7ac43ff46 h1:NRTg8JOXCxcIA1lAgD74iYud0rbshbWOB3Ou4+Huil8=
|
||||||
github.com/pomerium/protoutil v0.0.0-20240813175624-47b7ac43ff46/go.mod h1:QqZmx6ZgPxz18va7kqoT4t/0yJtP7YFIDiT/W2n2fZ4=
|
github.com/pomerium/protoutil v0.0.0-20240813175624-47b7ac43ff46/go.mod h1:QqZmx6ZgPxz18va7kqoT4t/0yJtP7YFIDiT/W2n2fZ4=
|
||||||
github.com/pomerium/webauthn v0.0.0-20240603205124-0428df511172 h1:TqoPqRgXSHpn+tEJq6H72iCS5pv66j3rPprThUEZg0E=
|
github.com/pomerium/webauthn v0.0.0-20240603205124-0428df511172 h1:TqoPqRgXSHpn+tEJq6H72iCS5pv66j3rPprThUEZg0E=
|
||||||
|
@ -573,6 +599,9 @@ github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KW
|
||||||
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
|
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||||
|
@ -588,6 +617,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke
|
||||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||||
|
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
||||||
|
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||||
|
@ -853,8 +884,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
@ -900,6 +931,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
@ -915,8 +947,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.opentelemetry.io/otel"
|
"go.opentelemetry.io/otel"
|
||||||
tracev1 "go.opentelemetry.io/proto/otlp/trace/v1"
|
tracev1 "go.opentelemetry.io/proto/otlp/trace/v1"
|
||||||
|
v1 "go.opentelemetry.io/proto/otlp/trace/v1"
|
||||||
"go.uber.org/mock/gomock"
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -283,6 +284,32 @@ func TestSyncClient(t *testing.T) {
|
||||||
assert.ErrorIs(t, sc.Stop(context.Background()), trace.ErrNoClient)
|
assert.ErrorIs(t, sc.Stop(context.Background()), trace.ErrNoClient)
|
||||||
assert.NoError(t, sc.Update(context.Background(), nil))
|
assert.NoError(t, sc.Update(context.Background(), nil))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("repeated updates", func(t *testing.T) {
|
||||||
|
sc := trace.NewSyncClient(nil)
|
||||||
|
for range 1000 {
|
||||||
|
sc.Update(context.Background(), &sleepClient{})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type sleepClient struct{}
|
||||||
|
|
||||||
|
// Start implements otlptrace.Client.
|
||||||
|
func (n sleepClient) Start(context.Context) error {
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop implements otlptrace.Client.
|
||||||
|
func (n sleepClient) Stop(context.Context) error {
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UploadTraces implements otlptrace.Client.
|
||||||
|
func (n sleepClient) UploadTraces(context.Context, []*v1.ResourceSpans) error {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type errHandler struct {
|
type errHandler struct {
|
||||||
|
|
|
@ -115,6 +115,7 @@ func GetDomainsForURL(u *url.URL, includeDefaultPort bool) []string {
|
||||||
|
|
||||||
// tcp+https://ssh.example.com:22
|
// tcp+https://ssh.example.com:22
|
||||||
// udp+https://ssh.example.com:22
|
// udp+https://ssh.example.com:22
|
||||||
|
// ssh://ssh.example.com:22
|
||||||
// => ssh.example.com:22
|
// => ssh.example.com:22
|
||||||
// tcp+https://proxy.example.com/ssh.example.com:22
|
// tcp+https://proxy.example.com/ssh.example.com:22
|
||||||
// udp+https://proxy.example.com/ssh.example.com:22
|
// udp+https://proxy.example.com/ssh.example.com:22
|
||||||
|
@ -130,10 +131,13 @@ func GetDomainsForURL(u *url.URL, includeDefaultPort bool) []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultPort string
|
var defaultPort string
|
||||||
if u.Scheme == "http" {
|
switch u.Scheme {
|
||||||
|
case "http":
|
||||||
defaultPort = "80"
|
defaultPort = "80"
|
||||||
} else {
|
case "https":
|
||||||
defaultPort = "443"
|
defaultPort = "443"
|
||||||
|
case "ssh":
|
||||||
|
defaultPort = "22"
|
||||||
}
|
}
|
||||||
|
|
||||||
// for hosts like 'example.com:1234' we only return one route
|
// for hosts like 'example.com:1234' we only return one route
|
||||||
|
|
|
@ -9,6 +9,8 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
envoy_service_auth_v3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
envoy_service_auth_v3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
|
||||||
|
extensions_ssh "github.com/pomerium/envoy-custom/api/extensions/filters/network/ssh"
|
||||||
|
|
||||||
"go.uber.org/automaxprocs/maxprocs"
|
"go.uber.org/automaxprocs/maxprocs"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
|
@ -267,6 +269,7 @@ func setupAuthorize(ctx context.Context, src config.Source, controlPlane *contro
|
||||||
return nil, fmt.Errorf("error creating authorize service: %w", err)
|
return nil, fmt.Errorf("error creating authorize service: %w", err)
|
||||||
}
|
}
|
||||||
envoy_service_auth_v3.RegisterAuthorizationServer(controlPlane.GRPCServer, svc)
|
envoy_service_auth_v3.RegisterAuthorizationServer(controlPlane.GRPCServer, svc)
|
||||||
|
extensions_ssh.RegisterStreamManagementServer(controlPlane.GRPCServer, svc)
|
||||||
|
|
||||||
log.Ctx(ctx).Info().Msg("enabled authorize service")
|
log.Ctx(ctx).Info().Msg("enabled authorize service")
|
||||||
src.OnConfigChange(ctx, svc.OnConfigChange)
|
src.OnConfigChange(ctx, svc.OnConfigChange)
|
||||||
|
|
|
@ -85,6 +85,7 @@ func (srv *Server) prepareRunEnvoyCommand(ctx context.Context, sharedArgs []stri
|
||||||
"--drain-time-s", "60",
|
"--drain-time-s", "60",
|
||||||
"--parent-shutdown-time-s", "120",
|
"--parent-shutdown-time-s", "120",
|
||||||
"--drain-strategy", "immediate",
|
"--drain-strategy", "immediate",
|
||||||
|
"--component-log-level", "matcher:trace,filter:debug",
|
||||||
)
|
)
|
||||||
restartEpoch.value++
|
restartEpoch.value++
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package envoy
|
package envoy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
|
@ -13,8 +10,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/pkg/envoy/files"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -76,34 +71,6 @@ func Extract() (fullEnvoyPath string, err error) {
|
||||||
return setupFullEnvoyPath, setupErr
|
return setupFullEnvoyPath, setupErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func extract(dstName string) (err error) {
|
|
||||||
checksum, err := hex.DecodeString(strings.Fields(files.Checksum())[0])
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("checksum %s: %w", files.Checksum(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
hr := &hashReader{
|
|
||||||
Hash: sha256.New(),
|
|
||||||
r: bytes.NewReader(files.Binary()),
|
|
||||||
}
|
|
||||||
|
|
||||||
dst, err := os.OpenFile(dstName, os.O_CREATE|os.O_WRONLY, ownerRX)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer func() { err = dst.Close() }()
|
|
||||||
|
|
||||||
if _, err = io.Copy(dst, io.LimitReader(hr, maxExpandedEnvoySize)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
sum := hr.Sum(nil)
|
|
||||||
if !bytes.Equal(sum, checksum) {
|
|
||||||
return fmt.Errorf("expected %x, got %x checksum", checksum, sum)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanTempDir(tmpDir string) {
|
func cleanTempDir(tmpDir string) {
|
||||||
d, err := os.Open(tmpDir)
|
d, err := os.Open(tmpDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
27
pkg/envoy/extract_debug_local.go
Normal file
27
pkg/envoy/extract_debug_local.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
//go:build debug_local_envoy
|
||||||
|
|
||||||
|
package envoy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/pomerium/pomerium/pkg/envoy/files"
|
||||||
|
)
|
||||||
|
|
||||||
|
var DebugLocalEnvoyPath string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
files.SetFiles(nil, "<external> _", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func extract(dstName string) (err error) {
|
||||||
|
if DebugLocalEnvoyPath == "" {
|
||||||
|
panic("DebugLocalEnvoyPath not set")
|
||||||
|
}
|
||||||
|
fullPath, err := filepath.EvalSymlinks(DebugLocalEnvoyPath)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return os.Symlink(fullPath, dstName)
|
||||||
|
}
|
43
pkg/envoy/extract_embed.go
Normal file
43
pkg/envoy/extract_embed.go
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
//go:build !debug_local_envoy
|
||||||
|
|
||||||
|
package envoy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pomerium/pomerium/pkg/envoy/files"
|
||||||
|
)
|
||||||
|
|
||||||
|
func extract(dstName string) (err error) {
|
||||||
|
checksum, err := hex.DecodeString(strings.Fields(files.Checksum())[0])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("checksum %s: %w", files.Checksum(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hr := &hashReader{
|
||||||
|
Hash: sha256.New(),
|
||||||
|
r: bytes.NewReader(files.Binary()),
|
||||||
|
}
|
||||||
|
|
||||||
|
dst, err := os.OpenFile(dstName, os.O_CREATE|os.O_WRONLY, ownerRX)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() { err = dst.Close() }()
|
||||||
|
|
||||||
|
if _, err = io.Copy(dst, io.LimitReader(hr, maxExpandedEnvoySize)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sum := hr.Sum(nil)
|
||||||
|
if !bytes.Equal(sum, checksum) {
|
||||||
|
return fmt.Errorf("expected %x, got %x checksum", checksum, sum)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
//go:build darwin && amd64 && !embed_pomerium
|
//go:build darwin && amd64 && !embed_pomerium && !debug_local_envoy
|
||||||
|
|
||||||
package files
|
package files
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build darwin && arm64 && !embed_pomerium
|
//go:build darwin && arm64 && !embed_pomerium && !debug_local_envoy
|
||||||
// +build darwin,arm64,!embed_pomerium
|
// +build darwin,arm64,!embed_pomerium,!debug_local_envoy
|
||||||
|
|
||||||
package files
|
package files
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//go:build embed_pomerium
|
//go:build embed_pomerium || debug_local_envoy
|
||||||
|
|
||||||
package files
|
package files
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build linux && amd64 && !embed_pomerium
|
//go:build linux && amd64 && !embed_pomerium && !debug_local_envoy
|
||||||
// +build linux,amd64,!embed_pomerium
|
// +build linux,amd64,!embed_pomerium,!debug_local_envoy
|
||||||
|
|
||||||
package files
|
package files
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build linux && arm64 && !embed_pomerium
|
//go:build linux && arm64 && !embed_pomerium && !debug_local_envoy
|
||||||
// +build linux,arm64,!embed_pomerium
|
// +build linux,arm64,!embed_pomerium,!debug_local_envoy
|
||||||
|
|
||||||
package files
|
package files
|
||||||
|
|
||||||
|
|
|
@ -1,39 +1,43 @@
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package pomerium.config;
|
package pomerium.config;
|
||||||
option go_package = "github.com/pomerium/pomerium/pkg/grpc/config";
|
|
||||||
|
|
||||||
import "google/protobuf/duration.proto";
|
|
||||||
import "google/protobuf/struct.proto";
|
|
||||||
import "envoy/config/cluster/v3/cluster.proto";
|
import "envoy/config/cluster/v3/cluster.proto";
|
||||||
import "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto";
|
import "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto";
|
||||||
|
import "google/protobuf/duration.proto";
|
||||||
|
import "google/protobuf/struct.proto";
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/pomerium/pomerium/pkg/grpc/config";
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
repeated Route routes = 2;
|
repeated Route routes = 2;
|
||||||
Settings settings = 3;
|
Settings settings = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RouteRewriteHeader {
|
message RouteRewriteHeader {
|
||||||
string header = 1;
|
string header = 1;
|
||||||
oneof matcher { string prefix = 3; }
|
oneof matcher {
|
||||||
|
string prefix = 3;
|
||||||
|
}
|
||||||
string value = 2;
|
string value = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RouteRedirect {
|
message RouteRedirect {
|
||||||
optional bool https_redirect = 1;
|
optional bool https_redirect = 1;
|
||||||
optional string scheme_redirect = 2;
|
optional string scheme_redirect = 2;
|
||||||
optional string host_redirect = 3;
|
optional string host_redirect = 3;
|
||||||
optional uint32 port_redirect = 4;
|
optional uint32 port_redirect = 4;
|
||||||
optional string path_redirect = 5;
|
optional string path_redirect = 5;
|
||||||
optional string prefix_rewrite = 6;
|
optional string prefix_rewrite = 6;
|
||||||
optional int32 response_code = 7;
|
optional int32 response_code = 7;
|
||||||
optional bool strip_query = 8;
|
optional bool strip_query = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RouteDirectResponse {
|
message RouteDirectResponse {
|
||||||
uint32 status = 1;
|
uint32 status = 1;
|
||||||
string body = 2;
|
string body = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum IssuerFormat {
|
enum IssuerFormat {
|
||||||
|
@ -47,13 +51,13 @@ enum IssuerFormat {
|
||||||
|
|
||||||
// Next ID: 69.
|
// Next ID: 69.
|
||||||
message Route {
|
message Route {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
string description = 67;
|
string description = 67;
|
||||||
string logo_url = 68;
|
string logo_url = 68;
|
||||||
|
|
||||||
string from = 2;
|
string from = 2;
|
||||||
repeated string to = 3;
|
repeated string to = 3;
|
||||||
RouteRedirect redirect = 34;
|
RouteRedirect redirect = 34;
|
||||||
RouteDirectResponse response = 62;
|
RouteDirectResponse response = 62;
|
||||||
|
|
||||||
// https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/endpoint/v3/endpoint_components.proto#envoy-v3-api-msg-config-endpoint-v3-lbendpoint
|
// https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/endpoint/v3/endpoint_components.proto#envoy-v3-api-msg-config-endpoint-v3-lbendpoint
|
||||||
|
@ -63,87 +67,88 @@ message Route {
|
||||||
// len(load_balancing_weights)
|
// len(load_balancing_weights)
|
||||||
repeated uint32 load_balancing_weights = 37;
|
repeated uint32 load_balancing_weights = 37;
|
||||||
|
|
||||||
repeated string allowed_users = 4 [ deprecated = true ];
|
repeated string allowed_users = 4 [deprecated = true];
|
||||||
// repeated string allowed_groups = 5 [ deprecated = true ];
|
// repeated string allowed_groups = 5 [ deprecated = true ];
|
||||||
repeated string allowed_domains = 6 [ deprecated = true ];
|
repeated string allowed_domains = 6 [deprecated = true];
|
||||||
map<string, google.protobuf.ListValue> allowed_idp_claims = 32
|
map<string, google.protobuf.ListValue> allowed_idp_claims = 32 [deprecated = true];
|
||||||
[ deprecated = true ];
|
|
||||||
|
|
||||||
string prefix = 7;
|
string prefix = 7;
|
||||||
string path = 8;
|
string path = 8;
|
||||||
string regex = 9;
|
string regex = 9;
|
||||||
|
|
||||||
string prefix_rewrite = 29;
|
string prefix_rewrite = 29;
|
||||||
string regex_rewrite_pattern = 30;
|
string regex_rewrite_pattern = 30;
|
||||||
string regex_rewrite_substitution = 31;
|
string regex_rewrite_substitution = 31;
|
||||||
optional int64 regex_priority_order = 61;
|
optional int64 regex_priority_order = 61;
|
||||||
|
|
||||||
bool cors_allow_preflight = 10;
|
bool cors_allow_preflight = 10;
|
||||||
bool allow_public_unauthenticated_access = 11;
|
bool allow_public_unauthenticated_access = 11;
|
||||||
bool allow_any_authenticated_user = 33;
|
bool allow_any_authenticated_user = 33;
|
||||||
google.protobuf.Duration timeout = 12;
|
google.protobuf.Duration timeout = 12;
|
||||||
google.protobuf.Duration idle_timeout = 43;
|
google.protobuf.Duration idle_timeout = 43;
|
||||||
bool allow_websockets = 13;
|
bool allow_websockets = 13;
|
||||||
bool allow_spdy = 44;
|
bool allow_spdy = 44;
|
||||||
|
|
||||||
bool tls_skip_verify = 14;
|
bool tls_skip_verify = 14;
|
||||||
string tls_server_name = 15;
|
string tls_server_name = 15;
|
||||||
string tls_upstream_server_name = 57;
|
string tls_upstream_server_name = 57;
|
||||||
string tls_downstream_server_name = 58;
|
string tls_downstream_server_name = 58;
|
||||||
string tls_custom_ca = 16;
|
string tls_custom_ca = 16;
|
||||||
string tls_custom_ca_file = 17;
|
string tls_custom_ca_file = 17;
|
||||||
|
|
||||||
string tls_client_cert = 18;
|
string tls_client_cert = 18;
|
||||||
string tls_client_key = 19;
|
string tls_client_key = 19;
|
||||||
string tls_client_cert_file = 20;
|
string tls_client_cert_file = 20;
|
||||||
string tls_client_key_file = 21;
|
string tls_client_key_file = 21;
|
||||||
string tls_downstream_client_ca = 38;
|
string tls_downstream_client_ca = 38;
|
||||||
string tls_downstream_client_ca_file = 39;
|
string tls_downstream_client_ca_file = 39;
|
||||||
|
|
||||||
bool tls_upstream_allow_renegotiation = 60;
|
bool tls_upstream_allow_renegotiation = 60;
|
||||||
|
|
||||||
map<string, string> set_request_headers = 22;
|
map<string, string> set_request_headers = 22;
|
||||||
repeated string remove_request_headers = 23;
|
repeated string remove_request_headers = 23;
|
||||||
map<string, string> set_response_headers = 41;
|
map<string, string> set_response_headers = 41;
|
||||||
repeated RouteRewriteHeader rewrite_response_headers = 40;
|
repeated RouteRewriteHeader rewrite_response_headers = 40;
|
||||||
// AuthorizationHeaderMode set_authorization_header = 54;
|
// AuthorizationHeaderMode set_authorization_header = 54;
|
||||||
|
|
||||||
bool preserve_host_header = 24;
|
bool preserve_host_header = 24;
|
||||||
optional bool pass_identity_headers = 25;
|
optional bool pass_identity_headers = 25;
|
||||||
|
|
||||||
string kubernetes_service_account_token = 26;
|
string kubernetes_service_account_token = 26;
|
||||||
string kubernetes_service_account_token_file = 64;
|
string kubernetes_service_account_token_file = 64;
|
||||||
bool enable_google_cloud_serverless_authentication = 42;
|
bool enable_google_cloud_serverless_authentication = 42;
|
||||||
IssuerFormat jwt_issuer_format = 65;
|
IssuerFormat jwt_issuer_format = 65;
|
||||||
repeated string jwt_groups_filter = 66;
|
repeated string jwt_groups_filter = 66;
|
||||||
|
|
||||||
envoy.config.cluster.v3.Cluster envoy_opts = 36;
|
envoy.config.cluster.v3.Cluster envoy_opts = 36;
|
||||||
|
|
||||||
repeated Policy policies = 27;
|
repeated Policy policies = 27;
|
||||||
repeated PPLPolicy ppl_policies = 63;
|
repeated PPLPolicy ppl_policies = 63;
|
||||||
string id = 28;
|
string id = 28;
|
||||||
|
|
||||||
optional string host_rewrite = 50;
|
optional string host_rewrite = 50;
|
||||||
optional string host_rewrite_header = 51;
|
optional string host_rewrite_header = 51;
|
||||||
optional string host_path_regex_rewrite_pattern = 52;
|
optional string host_path_regex_rewrite_pattern = 52;
|
||||||
optional string host_path_regex_rewrite_substitution = 53;
|
optional string host_path_regex_rewrite_substitution = 53;
|
||||||
|
|
||||||
optional string idp_client_id = 55;
|
optional string idp_client_id = 55;
|
||||||
optional string idp_client_secret = 56;
|
optional string idp_client_secret = 56;
|
||||||
bool show_error_details = 59;
|
bool show_error_details = 59;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PPLPolicy { bytes raw = 1; }
|
message PPLPolicy {
|
||||||
|
bytes raw = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message Policy {
|
message Policy {
|
||||||
string id = 1;
|
string id = 1;
|
||||||
string name = 2;
|
string name = 2;
|
||||||
repeated string allowed_users = 3;
|
repeated string allowed_users = 3;
|
||||||
// repeated string allowed_groups = 4;
|
// repeated string allowed_groups = 4;
|
||||||
repeated string allowed_domains = 5;
|
repeated string allowed_domains = 5;
|
||||||
map<string, google.protobuf.ListValue> allowed_idp_claims = 7;
|
map<string, google.protobuf.ListValue> allowed_idp_claims = 7;
|
||||||
repeated string rego = 6;
|
repeated string rego = 6;
|
||||||
optional string source_ppl = 10;
|
optional string source_ppl = 10;
|
||||||
|
|
||||||
string explanation = 8;
|
string explanation = 8;
|
||||||
string remediation = 9;
|
string remediation = 9;
|
||||||
|
@ -152,150 +157,181 @@ message Policy {
|
||||||
// Next ID: 138.
|
// Next ID: 138.
|
||||||
message Settings {
|
message Settings {
|
||||||
message Certificate {
|
message Certificate {
|
||||||
bytes cert_bytes = 3;
|
bytes cert_bytes = 3;
|
||||||
bytes key_bytes = 4;
|
bytes key_bytes = 4;
|
||||||
string id = 5;
|
string id = 5;
|
||||||
|
}
|
||||||
|
message StringList {
|
||||||
|
repeated string values = 1;
|
||||||
}
|
}
|
||||||
message StringList { repeated string values = 1; }
|
|
||||||
|
|
||||||
optional string installation_id = 71;
|
optional string installation_id = 71;
|
||||||
optional string log_level = 3;
|
optional string log_level = 3;
|
||||||
optional StringList access_log_fields = 114;
|
optional StringList access_log_fields = 114;
|
||||||
optional StringList authorize_log_fields = 115;
|
optional StringList authorize_log_fields = 115;
|
||||||
optional string proxy_log_level = 4;
|
optional string proxy_log_level = 4;
|
||||||
optional string shared_secret = 5;
|
optional string shared_secret = 5;
|
||||||
optional string services = 6;
|
optional string services = 6;
|
||||||
optional string address = 7;
|
optional string address = 7;
|
||||||
optional bool insecure_server = 8;
|
optional bool insecure_server = 8;
|
||||||
optional string dns_lookup_family = 60;
|
optional string dns_lookup_family = 60;
|
||||||
repeated Certificate certificates = 9;
|
repeated Certificate certificates = 9;
|
||||||
optional string http_redirect_addr = 10;
|
optional string http_redirect_addr = 10;
|
||||||
optional google.protobuf.Duration timeout_read = 11;
|
optional google.protobuf.Duration timeout_read = 11;
|
||||||
optional google.protobuf.Duration timeout_write = 12;
|
optional google.protobuf.Duration timeout_write = 12;
|
||||||
optional google.protobuf.Duration timeout_idle = 13;
|
optional google.protobuf.Duration timeout_idle = 13;
|
||||||
optional string authenticate_service_url = 14;
|
optional string authenticate_service_url = 14;
|
||||||
optional string authenticate_internal_service_url = 82;
|
optional string authenticate_internal_service_url = 82;
|
||||||
optional string signout_redirect_url = 93;
|
optional string signout_redirect_url = 93;
|
||||||
optional string authenticate_callback_path = 15;
|
optional string authenticate_callback_path = 15;
|
||||||
optional string cookie_name = 16;
|
optional string cookie_name = 16;
|
||||||
optional string cookie_secret = 17;
|
optional string cookie_secret = 17;
|
||||||
optional string cookie_domain = 18;
|
optional string cookie_domain = 18;
|
||||||
// optional bool cookie_secure = 19;
|
// optional bool cookie_secure = 19;
|
||||||
optional bool cookie_http_only = 20;
|
optional bool cookie_http_only = 20;
|
||||||
optional google.protobuf.Duration cookie_expire = 21;
|
optional google.protobuf.Duration cookie_expire = 21;
|
||||||
optional string cookie_same_site = 113;
|
optional string cookie_same_site = 113;
|
||||||
optional string idp_client_id = 22;
|
optional string idp_client_id = 22;
|
||||||
optional string idp_client_secret = 23;
|
optional string idp_client_secret = 23;
|
||||||
optional string idp_provider = 24;
|
optional string idp_provider = 24;
|
||||||
optional string idp_provider_url = 25;
|
optional string idp_provider_url = 25;
|
||||||
repeated string scopes = 26;
|
repeated string scopes = 26;
|
||||||
// optional string idp_service_account = 27;
|
// optional string idp_service_account = 27;
|
||||||
// optional google.protobuf.Duration idp_refresh_directory_timeout = 28;
|
// optional google.protobuf.Duration idp_refresh_directory_timeout = 28;
|
||||||
// optional google.protobuf.Duration idp_refresh_directory_interval = 29;
|
// optional google.protobuf.Duration idp_refresh_directory_interval = 29;
|
||||||
map<string, string> request_params = 30;
|
map<string, string> request_params = 30;
|
||||||
repeated string authorize_service_urls = 32;
|
repeated string authorize_service_urls = 32;
|
||||||
optional string authorize_internal_service_url = 83;
|
optional string authorize_internal_service_url = 83;
|
||||||
optional string override_certificate_name = 33;
|
optional string override_certificate_name = 33;
|
||||||
optional string certificate_authority = 34;
|
optional string certificate_authority = 34;
|
||||||
optional string derive_tls = 96;
|
optional string derive_tls = 96;
|
||||||
optional string signing_key = 36;
|
optional string signing_key = 36;
|
||||||
map<string, string> set_response_headers = 69;
|
map<string, string> set_response_headers = 69;
|
||||||
// repeated string jwt_claims_headers = 37;
|
// repeated string jwt_claims_headers = 37;
|
||||||
map<string, string> jwt_claims_headers = 63;
|
map<string, string> jwt_claims_headers = 63;
|
||||||
repeated string jwt_groups_filter = 119;
|
repeated string jwt_groups_filter = 119;
|
||||||
optional google.protobuf.Duration default_upstream_timeout = 39;
|
optional google.protobuf.Duration default_upstream_timeout = 39;
|
||||||
optional string metrics_address = 40;
|
optional string metrics_address = 40;
|
||||||
optional string metrics_basic_auth = 64;
|
optional string metrics_basic_auth = 64;
|
||||||
optional Certificate metrics_certificate = 65;
|
optional Certificate metrics_certificate = 65;
|
||||||
optional string metrics_client_ca = 66;
|
optional string metrics_client_ca = 66;
|
||||||
optional string otel_traces_exporter = 121;
|
optional string otel_traces_exporter = 121;
|
||||||
optional double otel_traces_sampler_arg = 122;
|
optional double otel_traces_sampler_arg = 122;
|
||||||
repeated string otel_resource_attributes = 123;
|
repeated string otel_resource_attributes = 123;
|
||||||
optional string otel_log_level = 124;
|
optional string otel_log_level = 124;
|
||||||
optional int32 otel_attribute_value_length_limit = 125;
|
optional int32 otel_attribute_value_length_limit = 125;
|
||||||
optional string otel_exporter_otlp_endpoint = 126;
|
optional string otel_exporter_otlp_endpoint = 126;
|
||||||
optional string otel_exporter_otlp_traces_endpoint = 127;
|
optional string otel_exporter_otlp_traces_endpoint = 127;
|
||||||
optional string otel_exporter_otlp_protocol = 128;
|
optional string otel_exporter_otlp_protocol = 128;
|
||||||
optional string otel_exporter_otlp_traces_protocol = 129;
|
optional string otel_exporter_otlp_traces_protocol = 129;
|
||||||
repeated string otel_exporter_otlp_headers = 130;
|
repeated string otel_exporter_otlp_headers = 130;
|
||||||
repeated string otel_exporter_otlp_traces_headers = 131;
|
repeated string otel_exporter_otlp_traces_headers = 131;
|
||||||
optional google.protobuf.Duration otel_exporter_otlp_timeout = 132;
|
optional google.protobuf.Duration otel_exporter_otlp_timeout = 132;
|
||||||
optional google.protobuf.Duration otel_exporter_otlp_traces_timeout = 133;
|
optional google.protobuf.Duration otel_exporter_otlp_traces_timeout = 133;
|
||||||
optional google.protobuf.Duration otel_bsp_schedule_delay = 134;
|
optional google.protobuf.Duration otel_bsp_schedule_delay = 134;
|
||||||
optional int32 otel_bsp_max_export_batch_size = 135;
|
optional int32 otel_bsp_max_export_batch_size = 135;
|
||||||
reserved 41 to 45, 98; // legacy tracing fields
|
reserved 41 to 45, 98; // legacy tracing fields
|
||||||
optional string grpc_address = 46;
|
optional string grpc_address = 46;
|
||||||
optional bool grpc_insecure = 47;
|
optional bool grpc_insecure = 47;
|
||||||
optional google.protobuf.Duration grpc_client_timeout = 99;
|
optional google.protobuf.Duration grpc_client_timeout = 99;
|
||||||
reserved 100; // grpc_client_dns_roundrobin
|
reserved 100; // grpc_client_dns_roundrobin
|
||||||
// optional string forward_auth_url = 50;
|
// optional string forward_auth_url = 50;
|
||||||
repeated string databroker_service_urls = 52;
|
repeated string databroker_service_urls = 52;
|
||||||
optional string databroker_internal_service_url = 84;
|
optional string databroker_internal_service_url = 84;
|
||||||
optional string databroker_storage_type = 101;
|
optional string databroker_storage_type = 101;
|
||||||
optional string databroker_storage_connection_string = 102;
|
optional string databroker_storage_connection_string = 102;
|
||||||
reserved 106; // databroker_storage_tls_skip_verify
|
reserved 106; // databroker_storage_tls_skip_verify
|
||||||
optional DownstreamMtlsSettings downstream_mtls = 116;
|
optional DownstreamMtlsSettings downstream_mtls = 116;
|
||||||
// optional string client_ca = 53;
|
// optional string client_ca = 53;
|
||||||
// optional string client_crl = 74;
|
// optional string client_crl = 74;
|
||||||
optional string google_cloud_serverless_authentication_service_account = 55;
|
optional string google_cloud_serverless_authentication_service_account = 55;
|
||||||
optional bool use_proxy_protocol = 107;
|
optional bool use_proxy_protocol = 107;
|
||||||
optional bool autocert = 56;
|
optional bool autocert = 56;
|
||||||
optional string autocert_ca = 76;
|
optional string autocert_ca = 76;
|
||||||
optional string autocert_email = 77;
|
optional string autocert_email = 77;
|
||||||
optional bool autocert_use_staging = 57;
|
optional bool autocert_use_staging = 57;
|
||||||
optional string autocert_eab_key_id = 78;
|
optional string autocert_eab_key_id = 78;
|
||||||
optional string autocert_eab_mac_key = 79;
|
optional string autocert_eab_mac_key = 79;
|
||||||
optional bool autocert_must_staple = 58;
|
optional bool autocert_must_staple = 58;
|
||||||
optional string autocert_dir = 59;
|
optional string autocert_dir = 59;
|
||||||
optional string autocert_trusted_ca = 80;
|
optional string autocert_trusted_ca = 80;
|
||||||
optional bool skip_xff_append = 61;
|
optional bool skip_xff_append = 61;
|
||||||
optional uint32 xff_num_trusted_hops = 70;
|
optional uint32 xff_num_trusted_hops = 70;
|
||||||
optional string envoy_admin_access_log_path = 108;
|
optional string envoy_admin_access_log_path = 108;
|
||||||
optional string envoy_admin_profile_path = 109;
|
optional string envoy_admin_profile_path = 109;
|
||||||
optional string envoy_admin_address = 110;
|
optional string envoy_admin_address = 110;
|
||||||
optional string envoy_bind_config_source_address = 111;
|
optional string envoy_bind_config_source_address = 111;
|
||||||
optional bool envoy_bind_config_freebind = 112;
|
optional bool envoy_bind_config_freebind = 112;
|
||||||
repeated string programmatic_redirect_domain_whitelist = 68;
|
repeated string programmatic_redirect_domain_whitelist = 68;
|
||||||
optional envoy.extensions.filters.network.http_connection_manager.v3
|
optional envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.CodecType codec_type = 73;
|
||||||
.HttpConnectionManager.CodecType codec_type = 73;
|
|
||||||
// optional pomerium.crypt.PublicKeyEncryptionKey audit_key = 72;
|
// optional pomerium.crypt.PublicKeyEncryptionKey audit_key = 72;
|
||||||
optional string primary_color = 85;
|
optional string primary_color = 85;
|
||||||
optional string secondary_color = 86;
|
optional string secondary_color = 86;
|
||||||
optional string darkmode_primary_color = 87;
|
optional string darkmode_primary_color = 87;
|
||||||
optional string darkmode_secondary_color = 88;
|
optional string darkmode_secondary_color = 88;
|
||||||
optional string logo_url = 89;
|
optional string logo_url = 89;
|
||||||
optional string favicon_url = 90;
|
optional string favicon_url = 90;
|
||||||
optional string error_message_first_paragraph = 91;
|
optional string error_message_first_paragraph = 91;
|
||||||
optional bool pass_identity_headers = 117;
|
optional bool pass_identity_headers = 117;
|
||||||
map<string, bool> runtime_flags = 118;
|
map<string, bool> runtime_flags = 118;
|
||||||
optional uint32 http3_advertise_port = 136;
|
optional uint32 http3_advertise_port = 136;
|
||||||
optional string device_auth_client_type = 137;
|
optional string device_auth_client_type = 137;
|
||||||
}
|
}
|
||||||
|
|
||||||
message DownstreamMtlsSettings {
|
message DownstreamMtlsSettings {
|
||||||
optional string ca = 1;
|
optional string ca = 1;
|
||||||
optional string crl = 2;
|
optional string crl = 2;
|
||||||
optional MtlsEnforcementMode enforcement = 3;
|
optional MtlsEnforcementMode enforcement = 3;
|
||||||
repeated SANMatcher match_subject_alt_names = 4;
|
repeated SANMatcher match_subject_alt_names = 4;
|
||||||
optional uint32 max_verify_depth = 5;
|
optional uint32 max_verify_depth = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MtlsEnforcementMode {
|
enum MtlsEnforcementMode {
|
||||||
UNKNOWN = 0;
|
UNKNOWN = 0;
|
||||||
POLICY = 1;
|
POLICY = 1;
|
||||||
POLICY_WITH_DEFAULT_DENY = 2;
|
POLICY_WITH_DEFAULT_DENY = 2;
|
||||||
REJECT_CONNECTION = 3;
|
REJECT_CONNECTION = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SANMatcher {
|
message SANMatcher {
|
||||||
enum SANType {
|
enum SANType {
|
||||||
SAN_TYPE_UNSPECIFIED = 0;
|
SAN_TYPE_UNSPECIFIED = 0;
|
||||||
EMAIL = 1;
|
EMAIL = 1;
|
||||||
DNS = 2;
|
DNS = 2;
|
||||||
URI = 3;
|
URI = 3;
|
||||||
IP_ADDRESS = 4;
|
IP_ADDRESS = 4;
|
||||||
USER_PRINCIPAL_NAME = 5;
|
USER_PRINCIPAL_NAME = 5;
|
||||||
}
|
}
|
||||||
SANType san_type = 1;
|
SANType san_type = 1;
|
||||||
string pattern = 2;
|
string pattern = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SSHCheckRequest {
|
||||||
|
string user_name = 1;
|
||||||
|
string service_name = 2;
|
||||||
|
string auth_method = 3;
|
||||||
|
|
||||||
|
string hostname = 4;
|
||||||
|
string route_id = 5;
|
||||||
|
bytes public_key = 6;
|
||||||
|
string public_key_alg = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SSHCheckResponse {
|
||||||
|
bool permit_port_forwarding = 1;
|
||||||
|
bool permit_agent_forwarding = 2;
|
||||||
|
bool permit_x11_forwarding = 3;
|
||||||
|
bool permit_pty = 4;
|
||||||
|
bool permit_user_rc = 5;
|
||||||
|
|
||||||
|
google.protobuf.Timestamp valid_before = 6;
|
||||||
|
google.protobuf.Duration valid_after = 7;
|
||||||
|
|
||||||
|
repeated string permit_open = 8;
|
||||||
|
repeated string permit_listen = 9;
|
||||||
|
|
||||||
|
optional string force_command = 10;
|
||||||
|
map<string, string> force_env = 11;
|
||||||
|
optional bool require_user_presence = 12;
|
||||||
|
optional bool require_verify = 13;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,6 @@ func (mp MockProvider) DeviceAccessToken(ctx context.Context, r *oauth2.DeviceAu
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeviceAuth implements Authenticator.
|
// DeviceAuth implements Authenticator.
|
||||||
func (mp MockProvider) DeviceAuth(w http.ResponseWriter, r *http.Request) (*oauth2.DeviceAuthResponse, error) {
|
func (mp MockProvider) DeviceAuth(_ context.Context) (*oauth2.DeviceAuthResponse, error) {
|
||||||
return &mp.DeviceAuthResponse, mp.DeviceAuthError
|
return &mp.DeviceAuthResponse, mp.DeviceAuthError
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,7 +183,7 @@ func (p *Provider) SignOut(_ http.ResponseWriter, _ *http.Request, _, _, _ strin
|
||||||
return oidc.ErrSignoutNotImplemented
|
return oidc.ErrSignoutNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) DeviceAuth(_ http.ResponseWriter, _ *http.Request) (*oauth2.DeviceAuthResponse, error) {
|
func (p *Provider) DeviceAuth(_ context.Context) (*oauth2.DeviceAuthResponse, error) {
|
||||||
return nil, oidc.ErrDeviceAuthNotImplemented
|
return nil, oidc.ErrDeviceAuthNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -257,7 +257,7 @@ func (p *Provider) SignOut(_ http.ResponseWriter, _ *http.Request, _, _, _ strin
|
||||||
return oidc.ErrSignoutNotImplemented
|
return oidc.ErrSignoutNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) DeviceAuth(_ http.ResponseWriter, _ *http.Request) (*oauth2.DeviceAuthResponse, error) {
|
func (p *Provider) DeviceAuth(_ context.Context) (*oauth2.DeviceAuthResponse, error) {
|
||||||
return nil, oidc.ErrDeviceAuthNotImplemented
|
return nil, oidc.ErrDeviceAuthNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ func (p *Provider) SignIn(w http.ResponseWriter, r *http.Request, state string)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) DeviceAuth(w http.ResponseWriter, r *http.Request) (*oauth2.DeviceAuthResponse, error) {
|
func (p *Provider) DeviceAuth(ctx context.Context) (*oauth2.DeviceAuthResponse, error) {
|
||||||
oa, err := p.GetOauthConfig()
|
oa, err := p.GetOauthConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -144,7 +144,7 @@ func (p *Provider) DeviceAuth(w http.ResponseWriter, r *http.Request) (*oauth2.D
|
||||||
opts = append(opts, oauth2.SetAuthURLParam("client_secret", oa.ClientSecret))
|
opts = append(opts, oauth2.SetAuthURLParam("client_secret", oa.ClientSecret))
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := oa.DeviceAuth(r.Context(), opts...)
|
resp, err := oa.DeviceAuth(ctx, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ type Authenticator interface {
|
||||||
SignOut(w http.ResponseWriter, r *http.Request, idTokenHint, authenticateSignedOutURL, redirectToURL string) error
|
SignOut(w http.ResponseWriter, r *http.Request, idTokenHint, authenticateSignedOutURL, redirectToURL string) error
|
||||||
|
|
||||||
// alternatives for these methods?
|
// alternatives for these methods?
|
||||||
DeviceAuth(w http.ResponseWriter, r *http.Request) (*oauth2.DeviceAuthResponse, error)
|
DeviceAuth(ctx context.Context) (*oauth2.DeviceAuthResponse, error)
|
||||||
DeviceAccessToken(ctx context.Context, r *oauth2.DeviceAuthResponse, state State) (*oauth2.Token, error)
|
DeviceAccessToken(ctx context.Context, r *oauth2.DeviceAuthResponse, state State) (*oauth2.Token, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue