-
Notifications
You must be signed in to change notification settings - Fork 1
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
OIDC Auth for Funnel, k8s state support #1
base: main
Are you sure you want to change the base?
Conversation
Going to get more complex with k8s config + OIDC, make it a file.
Want to run it in k8s, add a backend that uses a secret to store the data. While tailscale has one in their codebase, it's not suitable for our usage so we just add a simple one.
Want a dedicated listener, so we can selectively apply auth etc. So just add a new listener/server for that. Redirect to https for internal requests on funnel fqdn's, to keep URLs consistent. Rework startup/shutdown a little to be more graceful.
Adds OIDC auth to funnel endpoints, setting user header consistently. Optionally paths can be specified to be authless.
When running in a container, tailscale doesn't already exist so we can't talk to it. Just use a local listener, need to think about this more.
Need to think about the local tailscale daemon usage - it's there to figure out where to bind the discovery and metrics endpoints, but this doesn't work when it's running in a container. Might make a config option (ugh, checkboxes) for metrics listen - either set it to a fixed ip/port, or fallback to daemon discovery. But will think on it more |
@@ -0,0 +1,117 @@ | |||
package main |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may be able to use https://pkg.go.dev/tailscale.com/kube:
https://github.com/tailscale/tailscale/blob/main/cmd/containerboot/kube.go#L21-L23
I don't mind client-go tho, it's fine
@@ -205,98 +163,210 @@ func tsproxy(ctx context.Context) error { | |||
} | |||
} | |||
|
|||
for i, upstream := range upstreams { | |||
// https://go.dev/doc/faq#closures_and_goroutines | |||
i := i |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hehe nice
// OIDCClientID sets the OIDC client ID | ||
OIDCClientID string `json:"oidcClientID"` | ||
// OIDCClientSecret sets the OIDC client secret | ||
OIDCClientSecret string `json:"oidcClientSecret"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
be cool to support a file too, play nice with systemd-creds. For flags I usually do this:
if _, path, ok := strings.Cut(*cliSecret, "file://"); ok {
b, err := os.ReadFile(path)
if err != nil {
return err
}
s := strings.TrimSpace(string(b))
cliSecret = &s
}
but doesn't really work w/ a config file. Maybe oidcClientSecretFile?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also wondering if this should be on the root config struct, or do you plan on using a different issuer for some upstream(s)?
StateDir string `json:"stateDir"` | ||
// Kubernetes configures the proxy to run in a kubernetes cluster. In this | ||
// case the StateDir is ignored, and state managed in a secret. | ||
Kubernetes kubernetesConfig `json:"kubernetes"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*kubernetesConfig? then can drop the enabled field.
} | ||
listeners = append(listeners, ln) | ||
}*/ | ||
ln, err := net.Listen("tcp", "0.0.0.0:"+p) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use http://nuc10i5/sd
in my prom config, I guess I could make tsproxy.service listen on the node's tailscale IP using some ansible: {{ ansible_facts.tailscale0.ipv4.address }
alternatively could you check for the presence of a local socket? will think about it too.
// Proxy requests from non-funnel tagged nodes as is. | ||
// | ||
// TODO(lstoll) figure out why - and if end-user nodes would be tagged? | ||
if whois.Node.IsTagged() && !isFunnel { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I guess a config w/ a list of tags, or maybe node id to consider as end-users??
This adds OIDC auth for funnel usage. By default all funnel requests will require this, unless explicitly overridden.
Because this makes the config more complex, move to just using a file for it.
Add support for persisting state in a k8s secret too.
Add CI build, with docker image.
TODO