Skip to content

Commit

Permalink
GitHub proxy: git to prompt for password when tsh session expires
Browse files Browse the repository at this point in the history
  • Loading branch information
greedy52 committed Jan 28, 2025
1 parent f55257a commit d31ff45
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 5 deletions.
39 changes: 37 additions & 2 deletions api/utils/prompt/stdin.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@ limitations under the License.
package prompt

import (
"context"
"log/slog"
"os"
"runtime"
"sync"
)

var (
stdinMU sync.Mutex
stdin StdinReader
stdinMU sync.Mutex
stdin StdinReader
stdinTerminalFallback bool
)

// StdinReader contains ContextReader methods applicable to stdin.
Expand All @@ -42,6 +46,7 @@ func Stdin() StdinReader {
defer stdinMU.Unlock()
if stdin == nil {
cr := NewContextReader(os.Stdin)
cr = maybeUseStdinTerminalFallbackLocked(cr)
go cr.handleInterrupt()
stdin = cr
}
Expand Down Expand Up @@ -69,3 +74,33 @@ func NotifyExit() {
}
stdinMU.Unlock()
}

// EnableStdinTerminalFallback attempts to use a fallback like /dev/tty when stdin is
// not the terminal. This can be useful when tsh is called by another tool (e.g.
// git).
func EnableStdinTerminalFallback() {
stdinMU.Lock()
defer stdinMU.Unlock()
stdinTerminalFallback = true
}

func maybeUseStdinTerminalFallbackLocked(org *ContextReader) *ContextReader {
if !stdinTerminalFallback || runtime.GOOS == "windows" || org.IsTerminal() {
return org
}

devTTY, err := os.Open("/dev/tty")
if err != nil {
slog.DebugContext(context.Background(), "Failed to open /dev/tty", "error", err)
return org
}

cr := NewContextReader(devTTY)
if !cr.IsTerminal() {
slog.DebugContext(context.Background(), "/dev/tty is not a terminal")
return org
}

slog.DebugContext(context.Background(), "Using /dev/tty for prompt")
return cr
}
8 changes: 5 additions & 3 deletions tool/tsh/common/git_ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/gravitational/trace"

"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/utils/prompt"
"github.com/gravitational/teleport/lib/client"
)

Expand Down Expand Up @@ -61,9 +62,10 @@ func (c *gitSSHCommand) run(cf *CLIConf) error {
return trace.BadParameter("user-host %q is not GitHub", c.userHost)
}

// TODO(greedy52) when git calls tsh, tsh cannot prompt for password (e.g.
// user session expired) using provided stdin pipe. `tc.Login` should try
// hijacking "/dev/tty" and replace `prompt.Stdin` temporarily.
// This command is invoked by "git" so try some fallbacks when stdin is not
// the terminal.
prompt.EnableStdinTerminalFallback()

identity, err := getGitHubIdentity(cf, c.gitHubOrg)
if err != nil {
return trace.Wrap(err)
Expand Down

0 comments on commit d31ff45

Please sign in to comment.