diff options
author | Igor Drozdov <idrozdov@gitlab.com> | 2023-01-23 07:54:09 +0000 |
---|---|---|
committer | Igor Drozdov <idrozdov@gitlab.com> | 2023-01-23 07:54:09 +0000 |
commit | 7750f56e0c42d619b2a6354d99601d4b4f311867 (patch) | |
tree | e65f58f98c8bb075427ae16aee548410afebeb96 | |
parent | ad172bf0c9688238bc014d2ded2b181ae0b6e45a (diff) | |
parent | 51ea0f50f52d5d1dade02aadff3c163a0a792779 (diff) | |
download | gitlab-shell-7750f56e0c42d619b2a6354d99601d4b4f311867.tar.gz |
Merge branch '196-add-kerberos-support' into 'main'
Add support for the gssapi-with-mic auth method
Closes #196
See merge request https://gitlab.com/gitlab-org/gitlab-shell/-/merge_requests/682
Merged-by: Igor Drozdov <idrozdov@gitlab.com>
Approved-by: Alejandro RodrÃguez <alejandro@gitlab.com>
Approved-by: Patrick Bajao <ebajao@gitlab.com>
Approved-by: Costel Maxim <cmaxim@gitlab.com>
Approved-by: Igor Drozdov <idrozdov@gitlab.com>
Reviewed-by: Alejandro RodrÃguez <alejandro@gitlab.com>
Reviewed-by: Igor Drozdov <idrozdov@gitlab.com>
Reviewed-by: Patrick Bajao <ebajao@gitlab.com>
Reviewed-by: Rohit Shambhuni <rshambhuni@gitlab.com>
Co-authored-by: Lee Tickett <ltickett@gitlab.com>
Co-authored-by: Marin Hannache <git@mareo.fr>
-rw-r--r-- | cmd/gitlab-shell/command/command.go | 14 | ||||
-rw-r--r-- | cmd/gitlab-sshd/main.go | 2 | ||||
-rw-r--r-- | config.yml.example | 8 | ||||
-rw-r--r-- | go.mod | 1 | ||||
-rw-r--r-- | go.sum | 2 | ||||
-rw-r--r-- | internal/command/commandargs/shell.go | 13 | ||||
-rw-r--r-- | internal/config/config.go | 8 | ||||
-rw-r--r-- | internal/gitlabnet/accessverifier/client.go | 17 | ||||
-rw-r--r-- | internal/gitlabnet/accessverifier/client_test.go | 10 | ||||
-rw-r--r-- | internal/gitlabnet/discover/client.go | 2 | ||||
-rw-r--r-- | internal/gitlabnet/discover/client_test.go | 17 | ||||
-rw-r--r-- | internal/sshd/gssapi.go | 142 | ||||
-rw-r--r-- | internal/sshd/gssapi_test.go | 27 | ||||
-rw-r--r-- | internal/sshd/server_config.go | 23 | ||||
-rw-r--r-- | internal/sshd/server_config_test.go | 46 | ||||
-rw-r--r-- | internal/sshd/session.go | 19 | ||||
-rw-r--r-- | internal/sshd/session_test.go | 36 | ||||
-rw-r--r-- | internal/sshd/sshd.go | 11 |
18 files changed, 359 insertions, 39 deletions
diff --git a/cmd/gitlab-shell/command/command.go b/cmd/gitlab-shell/command/command.go index 08b3af6..b2a0266 100644 --- a/cmd/gitlab-shell/command/command.go +++ b/cmd/gitlab-shell/command/command.go @@ -44,6 +44,20 @@ func NewWithKey(gitlabKeyId string, env sshenv.Env, config *config.Config, readW return nil, disallowedcommand.Error } +func NewWithKrb5Principal(gitlabKrb5Principal string, env sshenv.Env, config *config.Config, readWriter *readwriter.ReadWriter) (command.Command, error) { + args, err := Parse(nil, env) + if err != nil { + return nil, err + } + + args.GitlabKrb5Principal = gitlabKrb5Principal + if cmd := Build(args, config, readWriter); cmd != nil { + return cmd, nil + } + + return nil, disallowedcommand.Error +} + func Parse(arguments []string, env sshenv.Env) (*commandargs.Shell, error) { args := &commandargs.Shell{Arguments: arguments, Env: env} diff --git a/cmd/gitlab-sshd/main.go b/cmd/gitlab-sshd/main.go index 330c25f..bc931f6 100644 --- a/cmd/gitlab-sshd/main.go +++ b/cmd/gitlab-sshd/main.go @@ -71,6 +71,8 @@ func main() { cfg.GitalyClient.InitSidechannelRegistry(ctx) + sshd.LoadGSSAPILib(&cfg.Server.GSSAPI) + server, err := sshd.NewServer(cfg) if err != nil { log.WithError(err).Fatal("Failed to start GitLab built-in sshd") diff --git a/config.yml.example b/config.yml.example index 0154723..886fde0 100644 --- a/config.yml.example +++ b/config.yml.example @@ -107,3 +107,11 @@ sshd: - /run/secrets/ssh-hostkeys/ssh_host_rsa_key-cert.pub - /run/secrets/ssh-hostkeys/ssh_host_ecdsa_key-cert.pub - /run/secrets/ssh-hostkeys/ssh_host_ed25519_key-cert.pub + # GSSAPI-related settings + gssapi: + # Enable the gssapi-with-mic authentication method. Defaults to false. + enabled: false + # Keytab path. Defaults to "", system default (usually /etc/krb5.keytab). + keytab: "" + # The Kerberos service name to be used by sshd. Defaults to "", accepts any service name in keytab file. + service_principal_name: "" @@ -9,6 +9,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.1 github.com/mattn/go-shellwords v1.0.11 github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a + github.com/openshift/gssapi v0.0.0-20161010215902-5fb4217df13b github.com/otiai10/copy v1.4.2 github.com/pires/go-proxyproto v0.6.2 github.com/prometheus/client_golang v1.13.1 @@ -277,6 +277,8 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= +github.com/openshift/gssapi v0.0.0-20161010215902-5fb4217df13b h1:it0YPE/evO6/m8t8wxis9KFI2F/aleOKsI6d9uz0cEk= +github.com/openshift/gssapi v0.0.0-20161010215902-5fb4217df13b/go.mod h1:tNrEB5k8SI+g5kOlsCmL2ELASfpqEofI0+FLBgBdN08= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= diff --git a/internal/command/commandargs/shell.go b/internal/command/commandargs/shell.go index 0b1e161..616d7e3 100644 --- a/internal/command/commandargs/shell.go +++ b/internal/command/commandargs/shell.go @@ -26,12 +26,13 @@ var ( ) type Shell struct { - Arguments []string - GitlabUsername string - GitlabKeyId string - SshArgs []string - CommandType CommandType - Env sshenv.Env + Arguments []string + GitlabUsername string + GitlabKeyId string + GitlabKrb5Principal string + SshArgs []string + CommandType CommandType + Env sshenv.Env } func (s *Shell) Parse() error { diff --git a/internal/config/config.go b/internal/config/config.go index b52f6f7..207517b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -23,6 +23,13 @@ const ( type YamlDuration time.Duration +type GSSAPIConfig struct { + Enabled bool `yaml:"enabled,omitempty"` + Keytab string `yaml:"keytab,omitempty"` + ServicePrincipalName string `yaml:"service_principal_name,omitempty"` + LibPath string +} + type ServerConfig struct { Listen string `yaml:"listen,omitempty"` ProxyProtocol bool `yaml:"proxy_protocol,omitempty"` @@ -41,6 +48,7 @@ type ServerConfig struct { MACs []string `yaml:"macs"` KexAlgorithms []string `yaml:"kex_algorithms"` Ciphers []string `yaml:"ciphers"` + GSSAPI GSSAPIConfig `yaml:"gssapi,omitempty"` } type HttpSettingsConfig struct { diff --git a/internal/gitlabnet/accessverifier/client.go b/internal/gitlabnet/accessverifier/client.go index ca81ad1..8554d9b 100644 --- a/internal/gitlabnet/accessverifier/client.go +++ b/internal/gitlabnet/accessverifier/client.go @@ -22,13 +22,14 @@ type Client struct { } type Request struct { - Action commandargs.CommandType `json:"action"` - Repo string `json:"project"` - Changes string `json:"changes"` - Protocol string `json:"protocol"` - KeyId string `json:"key_id,omitempty"` - Username string `json:"username,omitempty"` - CheckIp string `json:"check_ip,omitempty"` + Action commandargs.CommandType `json:"action"` + Repo string `json:"project"` + Changes string `json:"changes"` + Protocol string `json:"protocol"` + KeyId string `json:"key_id,omitempty"` + Username string `json:"username,omitempty"` + Krb5Principal string `json:"krb5principal,omitempty"` + CheckIp string `json:"check_ip,omitempty"` } type Gitaly struct { @@ -81,6 +82,8 @@ func (c *Client) Verify(ctx context.Context, args *commandargs.Shell, action com if args.GitlabUsername != "" { request.Username = args.GitlabUsername + } else if args.GitlabKrb5Principal != "" { + request.Krb5Principal = args.GitlabKrb5Principal } else { request.KeyId = args.GitlabKeyId } diff --git a/internal/gitlabnet/accessverifier/client_test.go b/internal/gitlabnet/accessverifier/client_test.go index 6a187f2..f2c88a5 100644 --- a/internal/gitlabnet/accessverifier/client_test.go +++ b/internal/gitlabnet/accessverifier/client_test.go @@ -56,7 +56,7 @@ func buildExpectedResponse(who string) *Response { func TestSuccessfulResponses(t *testing.T) { okResponse := testResponse{body: responseBody(t, "allowed.json"), status: http.StatusOK} client := setup(t, - map[string]testResponse{"first": okResponse}, + map[string]testResponse{"first": okResponse, "test@TEST.TEST": okResponse}, map[string]testResponse{"1": okResponse}, ) @@ -73,6 +73,10 @@ func TestSuccessfulResponses(t *testing.T) { desc: "Provide username within the request", args: &commandargs.Shell{GitlabUsername: "first"}, who: "user-1", + }, { + desc: "Provide krb5principal within the request", + args: &commandargs.Shell{GitlabKrb5Principal: "test@TEST.TEST"}, + who: "user-1", }, } @@ -255,6 +259,10 @@ func setup(t *testing.T, userResponses, keyResponses map[string]testResponse) *C w.WriteHeader(tr.status) _, err := w.Write(tr.body) require.NoError(t, err) + } else if tr, ok := userResponses[requestBody.Krb5Principal]; ok { + w.WriteHeader(tr.status) + _, err := w.Write(tr.body) + require.NoError(t, err) } else if tr, ok := keyResponses[requestBody.KeyId]; ok { w.WriteHeader(tr.status) _, err := w.Write(tr.body) diff --git a/internal/gitlabnet/discover/client.go b/internal/gitlabnet/discover/client.go index 1e7d33f..75b904b 100644 --- a/internal/gitlabnet/discover/client.go +++ b/internal/gitlabnet/discover/client.go @@ -38,6 +38,8 @@ func (c *Client) GetByCommandArgs(ctx context.Context, args *commandargs.Shell) params.Add("username", args.GitlabUsername) } else if args.GitlabKeyId != "" { params.Add("key_id", args.GitlabKeyId) + } else if args.GitlabKrb5Principal != "" { + params.Add("krb5principal", args.GitlabKrb5Principal) } else { // There was no 'who' information, this matches the ruby error // message. diff --git a/internal/gitlabnet/discover/client_test.go b/internal/gitlabnet/discover/client_test.go index 1506eba..6208fb2 100644 --- a/internal/gitlabnet/discover/client_test.go +++ b/internal/gitlabnet/discover/client_test.go @@ -38,6 +38,13 @@ func init() { Name: "Jane Doe", } json.NewEncoder(w).Encode(body) + } else if r.URL.Query().Get("krb5principal") == "john-doe@TEST.TEST" { + body := &Response{ + UserId: 3, + Username: "john-doe", + Name: "John Doe", + } + json.NewEncoder(w).Encode(body) } else if r.URL.Query().Get("username") == "broken_message" { w.WriteHeader(http.StatusForbidden) body := &client.ErrorResponse{ @@ -76,6 +83,16 @@ func TestGetByUsername(t *testing.T) { require.Equal(t, &Response{UserId: 1, Username: "jane-doe", Name: "Jane Doe"}, result) } +func TestGetByKrb5Principal(t *testing.T) { + client := setup(t) + + params := url.Values{} + params.Add("krb5principal", "john-doe@TEST.TEST") + result, err := client.getResponse(context.Background(), params) + require.NoError(t, err) + require.Equal(t, &Response{UserId: 3, Username: "john-doe", Name: "John Doe"}, result) +} + func TestMissingUser(t *testing.T) { client := setup(t) diff --git a/internal/sshd/gssapi.go b/internal/sshd/gssapi.go new file mode 100644 index 0000000..bf65a15 --- /dev/null +++ b/internal/sshd/gssapi.go @@ -0,0 +1,142 @@ +package sshd + +import ( + "fmt" + + "github.com/openshift/gssapi" + + "gitlab.com/gitlab-org/gitlab-shell/v14/internal/config" + + "gitlab.com/gitlab-org/labkit/log" +) + +var lib *gssapi.Lib + +func LoadGSSAPILib(config *config.GSSAPIConfig) error { + var err error + + if config.Enabled { + options := &gssapi.Options{ + Krb5Ktname: config.Keytab, + } + + if config.LibPath != "" { + options.LibPath = config.LibPath + } + + lib, err = gssapi.Load(options) + + if err != nil { + log.WithError(err).Error("Unable to load GSSAPI library, gssapi-with-mic is disabled") + config.Enabled = false + } + } + + return err +} + +type OSGSSAPIServer struct { + Keytab string + ServicePrincipalName string + + contextId *gssapi.CtxId +} + +func (_ *OSGSSAPIServer) str2name(str string) (*gssapi.Name, error) { + strBuffer, err := lib.MakeBufferString(str) + if err != nil { + return nil, err + } + defer strBuffer.Release() + + return strBuffer.Name(lib.GSS_C_NO_OID) +} + +func (server *OSGSSAPIServer) AcceptSecContext( + token []byte, +) ( + outputToken []byte, + srcName string, + needContinue bool, + err error, +) { + tokenBuffer, err := lib.MakeBufferBytes(token) + if err != nil { + return + } + defer tokenBuffer.Release() + + var spn *gssapi.CredId = lib.GSS_C_NO_CREDENTIAL + if server.ServicePrincipalName != "" { + var name *gssapi.Name + name, err = server.str2name(server.ServicePrincipalName) + if err != nil { + return + } + defer name.Release() + + var actualMech *gssapi.OIDSet + spn, actualMech, _, err = lib.AcquireCred(name, 0, lib.GSS_C_NO_OID_SET, gssapi.GSS_C_ACCEPT) + if err != nil { + return + } + defer spn.Release() + defer actualMech.Release() + } + + ctxOut, srcNameName, _, outputTokenBuffer, _, _, _, err := lib.AcceptSecContext( + server.contextId, + spn, + tokenBuffer, + nil, + ) + if err == gssapi.ErrContinueNeeded { + needContinue = true + err = nil + } else if err != nil { + return + } + defer outputTokenBuffer.Release() + defer srcNameName.Release() + + outputToken = outputTokenBuffer.Bytes() + server.contextId = ctxOut + + return outputToken, srcNameName.String(), needContinue, err +} + +func (server *OSGSSAPIServer) VerifyMIC( + micField []byte, + micToken []byte, +) error { + if server.contextId == nil { + return fmt.Errorf("gssapi: uninitialized contextId") + } + + micFieldBuffer, err := lib.MakeBufferBytes(micField) + if err != nil { + return err + } + defer micFieldBuffer.Release() + micTokenBuffer, err := lib.MakeBufferBytes(micToken) + if err != nil { + return err + } + defer micTokenBuffer.Release() + + _, err = server.contextId.VerifyMIC(micFieldBuffer, micTokenBuffer) + return err + +} + +func (server *OSGSSAPIServer) DeleteSecContext() error { + if server.contextId == nil { + return nil + } + + err := server.contextId.DeleteSecContext() + if err == nil { + server.contextId = nil + } + return err +} diff --git a/internal/sshd/gssapi_test.go b/internal/sshd/gssapi_test.go new file mode 100644 index 0000000..f4f19cf --- /dev/null +++ b/internal/sshd/gssapi_test.go @@ -0,0 +1,27 @@ +package sshd + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "gitlab.com/gitlab-org/gitlab-shell/v14/internal/config" +) + +func TestLoadGSSAPILibSucces(t *testing.T) { + config := &config.GSSAPIConfig{Enabled: true} + err := LoadGSSAPILib(config) + + require.NotNil(t, lib) + require.Nil(t, err) + require.True(t, config.Enabled) +} + +func TestLoadGSSAPILibFailure(t *testing.T) { + config := &config.GSSAPIConfig{Enabled: true, LibPath: "/invalid"} + err := LoadGSSAPILib(config) + + require.Nil(t, lib) + require.NotNil(t, err) + require.False(t, config.Enabled) +} diff --git a/internal/sshd/server_config.go b/internal/sshd/server_config.go index c8b1e54..3c1fdbf 100644 --- a/internal/sshd/server_config.go +++ b/internal/sshd/server_config.go @@ -146,6 +146,26 @@ func (s *serverConfig) getAuthKey(ctx context.Context, user string, key ssh.Publ } func (s *serverConfig) get(ctx context.Context) *ssh.ServerConfig { + var gssapiWithMICConfig *ssh.GSSAPIWithMICConfig + if s.cfg.Server.GSSAPI.Enabled { + gssapiWithMICConfig = &ssh.GSSAPIWithMICConfig{ + AllowLogin: func(conn ssh.ConnMetadata, srcName string) (*ssh.Permissions, error) { + if conn.User() != s.cfg.User { + return nil, fmt.Errorf("unknown user") + } + + return &ssh.Permissions{ + // Record the Kerberos principal used for authentication. + Extensions: map[string]string{ + "krb5principal": srcName, + }, + }, nil + }, + Server: &OSGSSAPIServer{ + ServicePrincipalName: s.cfg.Server.GSSAPI.ServicePrincipalName, + }, + } + } sshCfg := &ssh.ServerConfig{ PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { res, err := s.getAuthKey(ctx, conn.User(), key) @@ -160,7 +180,8 @@ func (s *serverConfig) get(ctx context.Context) *ssh.ServerConfig { }, }, nil }, - ServerVersion: "SSH-2.0-GitLab-SSHD", + GSSAPIWithMICConfig: gssapiWithMICConfig, + ServerVersion: "SSH-2.0-GitLab-SSHD", } if len(s.cfg.Server.MACs) > 0 { diff --git a/internal/sshd/server_config_test.go b/internal/sshd/server_config_test.go index d98302f..d8e6370 100644 --- a/internal/sshd/server_config_test.go +++ b/internal/sshd/server_config_test.go @@ -171,6 +171,52 @@ func TestCustomAlgorithms(t *testing.T) { require.Equal(t, customCiphers, sshServerConfig.Ciphers) } +func TestGSSAPIWithMIC(t *testing.T) { + srvCfg := &serverConfig{ + cfg: &config.Config{ + Server: config.ServerConfig{ + GSSAPI: config.GSSAPIConfig{ + Enabled: true, + ServicePrincipalName: "host/test@TEST.TEST", + }, + }, + }, + } + sshServerConfig := srvCfg.get(context.Background()) + server := sshServerConfig.GSSAPIWithMICConfig.Server.(*OSGSSAPIServer) + + require.NotNil(t, sshServerConfig.GSSAPIWithMICConfig) + require.NotNil(t, sshServerConfig.GSSAPIWithMICConfig.AllowLogin) + require.NotNil(t, server) + require.Equal(t, server.ServicePrincipalName, "host/test@TEST.TEST") + + sshServerConfig.SetDefaults() + + require.NotNil(t, sshServerConfig.GSSAPIWithMICConfig) + require.NotNil(t, sshServerConfig.GSSAPIWithMICConfig.AllowLogin) + require.NotNil(t, server) + require.Equal(t, server.ServicePrincipalName, "host/test@TEST.TEST") +} + +func TestGSSAPIWithMICDisabled(t *testing.T) { + srvCfg := &serverConfig{ + cfg: &config.Config{ + Server: config.ServerConfig{ + GSSAPI: config.GSSAPIConfig{ + Enabled: false, + }, + }, + }, + } + sshServerConfig := srvCfg.get(context.Background()) + + require.Nil(t, sshServerConfig.GSSAPIWithMICConfig) + + sshServerConfig.SetDefaults() + + require.Nil(t, sshServerConfig.GSSAPIWithMICConfig) +} + func rsaPublicKey(t *testing.T) ssh.PublicKey { privateKey, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err) diff --git a/internal/sshd/session.go b/internal/sshd/session.go index 48cd86a..3394b2a 100644 --- a/internal/sshd/session.go +++ b/internal/sshd/session.go @@ -13,6 +13,7 @@ import ( grpcstatus "google.golang.org/grpc/status" shellCmd "gitlab.com/gitlab-org/gitlab-shell/v14/cmd/gitlab-shell/command" + "gitlab.com/gitlab-org/gitlab-shell/v14/internal/command" "gitlab.com/gitlab-org/gitlab-shell/v14/internal/command/readwriter" "gitlab.com/gitlab-org/gitlab-shell/v14/internal/command/shared/disallowedcommand" "gitlab.com/gitlab-org/gitlab-shell/v14/internal/config" @@ -23,10 +24,11 @@ import ( type session struct { // State set up by the connection - cfg *config.Config - channel ssh.Channel - gitlabKeyId string - remoteAddr string + cfg *config.Config + channel ssh.Channel + gitlabKeyId string + gitlabKrb5Principal string + remoteAddr string // State managed by the session execCmd string @@ -166,7 +168,14 @@ func (s *session) handleShell(ctx context.Context, req *ssh.Request) (uint32, er ErrOut: s.channel.Stderr(), } - cmd, err := shellCmd.NewWithKey(s.gitlabKeyId, env, s.cfg, rw) + var cmd command.Command + var err error + + if s.gitlabKrb5Principal != "" { + cmd, err = shellCmd.NewWithKrb5Principal(s.gitlabKrb5Principal, env, s.cfg, rw) + } else { + cmd, err = shellCmd.NewWithKey(s.gitlabKeyId, env, s.cfg, rw) + } if err != nil { if errors.Is(err, disallowedcommand.Error) { s.toStderr(ctx, "ERROR: Unknown command: %v\n", s.execCmd) diff --git a/internal/sshd/session_test.go b/internal/sshd/session_test.go index fe43342..d1bff7e 100644 --- a/internal/sshd/session_test.go +++ b/internal/sshd/session_test.go @@ -130,21 +130,29 @@ func TestHandleExec(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - out := &bytes.Buffer{} - f := &fakeChannel{stdErr: out} - s := &session{ - gitlabKeyId: "root", - channel: f, - cfg: &config.Config{GitlabUrl: url}, + sessions := []*session{ + { + gitlabKeyId: "root", + cfg: &config.Config{GitlabUrl: url}, + }, + { + gitlabKrb5Principal: "test@TEST.TEST", + cfg: &config.Config{GitlabUrl: url}, + }, + } + for _, s := range sessions { + out := &bytes.Buffer{} + f := &fakeChannel{stdErr: out} + r := &ssh.Request{Payload: tc.payload} + + s.channel = f + shouldContinue, err := s.handleExec(context.Background(), r) + + require.Equal(t, tc.expectedErr, err) + require.Equal(t, false, shouldContinue) + require.Equal(t, tc.sentRequestName, f.sentRequestName) + require.Equal(t, tc.sentRequestPayload, f.sentRequestPayload) } - r := &ssh.Request{Payload: tc.payload} - - shouldContinue, err := s.handleExec(context.Background(), r) - - require.Equal(t, tc.expectedErr, err) - require.Equal(t, false, shouldContinue) - require.Equal(t, tc.sentRequestName, f.sentRequestName) - require.Equal(t, tc.sentRequestPayload, f.sentRequestPayload) }) } } diff --git a/internal/sshd/sshd.go b/internal/sshd/sshd.go index d20286a..fbb5052 100644 --- a/internal/sshd/sshd.go +++ b/internal/sshd/sshd.go @@ -194,11 +194,12 @@ func (s *Server) handleConn(ctx context.Context, nconn net.Conn) { conn := newConnection(s.Config, nconn) conn.handle(ctx, s.serverConfig.get(ctx), func(sconn *ssh.ServerConn, channel ssh.Channel, requests <-chan *ssh.Request) error { session := &session{ - cfg: s.Config, - channel: channel, - gitlabKeyId: sconn.Permissions.Extensions["key-id"], - remoteAddr: remoteAddr, - started: time.Now(), + cfg: s.Config, + channel: channel, + gitlabKeyId: sconn.Permissions.Extensions["key-id"], + gitlabKrb5Principal: sconn.Permissions.Extensions["krb5principal"], + remoteAddr: remoteAddr, + started: time.Now(), } return session.handle(ctx, requests) |