Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GitHub proxy part 6: proxing Git using SSH transport #49980

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

greedy52
Copy link
Contributor

Related:

will stack another PR for tsh git ssh/config/clone commands on top of this

@greedy52 greedy52 mentioned this pull request Dec 10, 2024
14 tasks
Base automatically changed from STeve/48762_github_oauth_flow to master December 10, 2024 17:50
@greedy52 greedy52 changed the base branch from master to STeve/48762_audit_log December 11, 2024 02:53
@greedy52 greedy52 changed the base branch from STeve/48762_audit_log to master December 11, 2024 02:53
@greedy52 greedy52 marked this pull request as ready for review December 12, 2024 01:59
Comment on lines 194 to +197
// GitHubProxyCASSH uses same algorithms as UserCASSH.
GitHubProxyCASSH: RSA2048,
// GitClient uses same algorithms as UserCASSH.
GitClient: RSA2048,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why we're not defaulting to P256 or Ed25519 here? The comment for the legacy suite states "new features should always use the new algorithms".

Copy link
Contributor

@espadolini espadolini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that hooking into lib/srv/forward.Server to essentially add a completely separate mode gated by a flag (or like three different and potentially conflicting flags) is easier than writing something new that's going to be structurally guaranteed to work as intended just for the purpose of forwarding the ssh git protocol?

Comment on lines +1901 to +1902
// GitServerGetter defines a service to get Git servers.
services.GitServerGetter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If ClientI already has a way to get a gitserver.Client which has GetGitServer and ListGitServers, why do we need to extend ClientI with methods at the top level?

@@ -285,6 +286,11 @@ func (r *Router) DialHost(ctx context.Context, clientSrcAddr, clientDstAddr net.
return nil, trace.Wrap(err)
}
}
} else if target.GetGitHub() != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we have a subkind to check here? Let's try to safeguard ourselves against a regular ssh server getting a non-nil but empty github section due to serialization and deserialization mistakes.

@@ -418,6 +435,9 @@ func (r remoteSite) GetClusterNetworkingConfig(ctx context.Context) (types.Clust
// getServer attempts to locate a node matching the provided host and port in
// the provided site.
func getServer(ctx context.Context, host, port string, site site) (types.Server, error) {
if org, ok := types.GetGitHubOrgFromNodeAddr(host); ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if a regular SSH server has a hostname that matches the pattern we've decided to reserve for github orgs?

@@ -79,6 +80,8 @@ import (
// return nil, trace.Wrap(err)
// }
type Server struct {
component string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a "component"? Please add a godoc for this.

Comment on lines +522 to +524
if s.component == teleport.ComponentForwardingGit && s.targetServer != nil {
return s.targetServer
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if targetServer is nil but the component is set to ComponentForwardingGit?

Comment on lines +90 to +91
// gitServerWatcher provides the Git server set for the remote site
gitServerWatcher *services.GenericWatcher[types.Server, readonly.Server]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agentless SSH across clusters relies on the root cluster generating the credentials that must be trusted by the destination. Seeing as how the destination is github, and the credentials must be in a plugincredential in the root, what's the point of interacting with git servers in a leaf cluster?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resource watcher will also constantly spew errors and reset if the underlying event stream can't be initialized because the leaf auth server doesn't know about the existence of git_server.

@@ -233,6 +234,7 @@ func (h *AuthHandlers) CreateIdentityContext(sconn *ssh.ServerConn) (IdentityCon
}
identity.PreviousIdentityExpires = asTime
}
identity.GitHubUserID = certificate.Extensions[teleport.CertExtensionGitHubUserID]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have traits and roles and the only server that's going to interact with the github user ID is in our control (because it's a MITM server in the proxy) why do we need to bake anything in the SSH certificate of the user? Doing so also prevents us from having different user IDs for different orgs, for example.

//
// Sample command: git-upload-pack 'my-org/my-repo.git'
func parseSSHCommand(command string) (*sshCommand, error) {
gitService, path, ok := strings.Cut(strings.TrimSpace(command), " ")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use a real shell command lexer instead of writing something that appears to work but might accidentally let an attacker bypass auditing or authorization.

Comment on lines +47 to +50
"SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s",
"SHA256:br9IjFspm1vxR3iA35FWE+4VTyz1hYVLIE2t1/CeyWQ",
"SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM",
"SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://api.github.com/meta only lists three keys, I think that one of these four is the DSA key that's no longer used and was never supported by x/crypto/ssh anyway. Can we get rid of that?

Comment on lines +124 to +128
userExpires := c.IdentityExpires.Sub(c.Clock.Now())
if userExpires > defaultGitHubUserCertTTL {
return defaultGitHubUserCertTTL
}
return userExpires
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
userExpires := c.IdentityExpires.Sub(c.Clock.Now())
if userExpires > defaultGitHubUserCertTTL {
return defaultGitHubUserCertTTL
}
return userExpires
userTTL := c.IdentityExpires.Sub(c.Clock.Now())
return min(userTTL, defaultGitHubUserCertTTL)

@greedy52
Copy link
Contributor Author

greedy52 commented Dec 16, 2024

Are you sure that hooking into lib/srv/forward.Server to essentially add a completely separate mode gated by a flag (or like three different and potentially conflicting flags) is easier than writing something new that's going to be structurally guaranteed to work as intended just for the purpose of forwarding the ssh git protocol?

will do 👍

@greedy52
Copy link
Contributor Author

i am splitting out some parts of this PR to separate ones like

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants