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

Add TargetPort to RouteToApp & use it to route connections to multi-port TCP apps #49047

Merged
merged 17 commits into from
Dec 3, 2024

Conversation

ravicious
Copy link
Member

@ravicious ravicious commented Nov 15, 2024

#47706 made it so that it's possible to configure a multi-port TCP app. This PR makes it possible to generate a cert with TargetPort and then makes the app agent use that field from the cert to route the connection to the target port. This is described in the "Passing the port number from the client to the app agent" section of the RFD and backwards compatibility is described in the "Server-client compatibility" section.

Best reviewed commit-by-commit. The actual implementation is rather simple, but I had to change a bunch of stuff to make tests for this feature more terse.

I manually tested that this works by modifying the code in lib/teleterm that generates app certs to include a hardcoded TargetPort. Then I configured a TCP app with an appropriate port range with Postgres running on that port and then I connected to it. All of the audit events include a separate field with the target port.

@ravicious ravicious added do-not-merge no-changelog Indicates that a PR does not require a changelog entry labels Nov 15, 2024
Comment on lines -547 to -548
+ // long as the port is defined in the app spec. When specified, it must be between 1 and 65535 and
+ // the URI is expected to use this port as well.
Copy link
Member Author

Choose a reason for hiding this comment

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

It isn't true that the URI is expected to include TargetPort. This is a section that I forgot to update in the RFD PR when I was making this change.

Also wow, whatever GitHub uses for syntax highlighting breaks terribly when the things that being changed uses diff syntax. :~)

require.True(t, net.ParseIP(identity.LoginIP).IsLoopback())
require.Equal(t, []string{teleport.UsageAppsOnly}, identity.Usage)
require.Equal(t, "app-a", identity.RouteToApp.Name)
require.Equal(t, uint16(1337), identity.RouteToApp.TargetPort)
Copy link
Member Author

Choose a reason for hiding this comment

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

I just copy-pasted the test case above and added a single line which checks TargetPort.

@ravicious ravicious marked this pull request as ready for review November 15, 2024 12:15
@ravicious
Copy link
Member Author

@marcoandredinis @espadolini I'm adding you both since you already have context on this. This is the last server-side change that's needed for multi-port TCP app access.

@github-actions github-actions bot added application-access rfd Request for Discussion size/md labels Nov 15, 2024
@ravicious ravicious removed the rfd Request for Discussion label Nov 15, 2024
api/utils/net/ports.go Outdated Show resolved Hide resolved
lib/srv/app/tcpserver.go Show resolved Hide resolved
}

if targetPort != addrPort {
return trace.BadParameter("target port is not equal to port number from URI (%d vs %d)", targetPort, addrPort)
Copy link
Member Author

Choose a reason for hiding this comment

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

This is one of those cases where I wish I could provide a more meaningful error message. In most cases, this is probably going to happen because of what's described in the comment for this function, but there's a chance it can happen due to a programmer error.

Maybe the error should say something like "attempt to connect to a TCP app with a multi-port cert where the target port from the cert does not match the port from the app URI (%d vs %q)"?

Saying just "target port is not equal to port number from URI" is certainly true, but it doesn't help you much unless you know how Teleport and multi-port TCP access work.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe the error should say something like "attempt to connect to a TCP app with a multi-port cert where the target port from the cert does not match the port from the app URI (%d vs %q)"?

I prefer that one, but I think we can go a step further and give the user some actionable. Maybe ask them to restart the App Service? Would re-login help here as well?

I'm not a fan of using x vs y, because it is not always clear what is x and y. And you need to check the source code to be sure which is which.
Can we use something like this instead?

Suggested change
return trace.BadParameter("target port is not equal to port number from URI (%d vs %d)", targetPort, addrPort)
return trace.BadParameter("target port is not equal to port number from URI target_port=%d uri_port=%d", targetPort, addrPort)

Copy link
Member Author

Choose a reason for hiding this comment

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

I prefer that one, but I think we can go a step further and give the user some actionable. Maybe ask them to restart the App Service? Would re-login help here as well?

The problem with giving some actionable here is that this is a client-side issue reported in server-side environment. We have some plans already to catch problems like this one on the client-side too, see #46169 (comment) and the "Incorrect port" section in the RFD.

lib/srv/app/tcpserver.go Show resolved Hide resolved
@ravicious ravicious requested a review from espadolini November 18, 2024 12:07
lib/tlsca/ca.go Outdated Show resolved Hide resolved
}

if targetPort != addrPort {
return trace.BadParameter("target port is not equal to port number from URI (%d vs %d)", targetPort, addrPort)
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe the error should say something like "attempt to connect to a TCP app with a multi-port cert where the target port from the cert does not match the port from the app URI (%d vs %q)"?

I prefer that one, but I think we can go a step further and give the user some actionable. Maybe ask them to restart the App Service? Would re-login help here as well?

I'm not a fan of using x vs y, because it is not always clear what is x and y. And you need to check the source code to be sure which is which.
Can we use something like this instead?

Suggested change
return trace.BadParameter("target port is not equal to port number from URI (%d vs %d)", targetPort, addrPort)
return trace.BadParameter("target port is not equal to port number from URI target_port=%d uri_port=%d", targetPort, addrPort)

lib/srv/app/tcpserver.go Outdated Show resolved Hide resolved
Base automatically changed from r7s/ports-app-spec to master December 3, 2024 12:59
@ravicious ravicious force-pushed the r7s/mp-route-to-app branch from 3964b36 to 0889510 Compare December 3, 2024 13:36
@ravicious ravicious enabled auto-merge December 3, 2024 13:36
@ravicious ravicious added this pull request to the merge queue Dec 3, 2024
Merged via the queue into master with commit 0ade3a8 Dec 3, 2024
43 checks passed
@ravicious ravicious deleted the r7s/mp-route-to-app branch December 3, 2024 14:14
@public-teleport-github-review-bot

@ravicious See the table below for backport results.

Branch Result
branch/v17 Failed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
application-access backport/branch/v17 no-changelog Indicates that a PR does not require a changelog entry size/md
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants