Close proxy listener if session is no longer active (#4850)

* Close proxy listener if session is no longer active
pull/4852/head
Todd 2 years ago committed by GitHub
parent 4fd49f00f6
commit 98b5e3fa52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -9,6 +9,7 @@ import (
"net/netip"
"time"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/targets"
)
@ -37,6 +38,7 @@ type Options struct {
WithSessionAuthorizationData *targets.SessionAuthorizationData
WithSkipSessionTeardown bool
withSessionTeardownTimeout time.Duration
withApiClient *api.Client
}
// Option is a function that takes in an options struct and sets values or
@ -129,3 +131,14 @@ func WithSessionTeardownTimeout(with time.Duration) Option {
return nil
}
}
// WithApiClient provides an optional Boundary API client
// Experimental: It is unclear whether the current usage of this option is the
// approach that we want to take in the long term. This may be removed at any
// point going forward.
func WithApiClient(with *api.Client) Option {
return func(o *Options) error {
o.withApiClient = with
return nil
}
}

@ -9,6 +9,7 @@ import (
"testing"
"time"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/targets"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -96,4 +97,15 @@ func Test_GetOpts(t *testing.T) {
require.NoError(t, err)
assert.Equal(3*time.Millisecond, opts.withSessionTeardownTimeout)
})
t.Run("withSessionsClient", func(t *testing.T) {
assert := assert.New(t)
opts, err := getOpts()
require.NoError(t, err)
assert.Nil(opts.withApiClient)
client, err := api.NewClient(nil)
require.NoError(t, err)
opts, err = getOpts(WithApiClient(client))
require.NoError(t, err)
assert.Equal(client, opts.withApiClient)
})
}

@ -15,6 +15,8 @@ import (
"sync/atomic"
"time"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/sessions"
"github.com/hashicorp/boundary/api/targets"
cleanhttp "github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/go-secure-stdlib/base62"
@ -37,6 +39,7 @@ type ClientProxy struct {
connectionsLeft *atomic.Int32
connsLeftCh chan int32
callerConnectionsLeftCh chan int32
apiClient *api.Client
sessionAuthzData *targets.SessionAuthorizationData
createTime time.Time
expiration time.Time
@ -97,6 +100,7 @@ func New(ctx context.Context, authzToken string, opt ...Option) (*ClientProxy, e
callerConnectionsLeftCh: opts.WithConnectionsLeftCh,
started: new(atomic.Bool),
skipSessionTeardown: opts.WithSkipSessionTeardown,
apiClient: opts.withApiClient,
}
if opts.WithListener != nil {
@ -260,6 +264,27 @@ func (p *ClientProxy) Start(opt ...Option) (retErr error) {
p.cancel()
return
}
// TODO: Determine if this is useful or if there is a better approach
// that we may use in the long term.
if p.apiClient != nil {
// If we can tell that the session for the connection we just
// closed is terminated, we can close the listener, otherwise
// might as well leave it open so the next connection can be
// tried.
sess, err := sessions.NewClient(p.apiClient).Read(p.ctx, p.sessionAuthzData.SessionId)
if err != nil || sess == nil || sess.Item == nil || sess.Item.TerminationReason == "" {
return
}
// We got a valid session response for the session we just
// closed a connection for. Since there is a termination reason
// we can treat the session as being terminated so no more
// connections will be able to be established.
fin <- fmt.Errorf("session no longer active")
listenerCloseFunc()
p.cancel()
}
}()
}
}()

Loading…
Cancel
Save