Merge pull request #392 from e-zk/windows-endpoint
This commit is contained in:
commit
0720473033
3 changed files with 116 additions and 9 deletions
|
@ -18,6 +18,7 @@
|
||||||
- Add support for writing ACL files with YAML [#359](https://github.com/juanfont/headscale/pull/359)
|
- Add support for writing ACL files with YAML [#359](https://github.com/juanfont/headscale/pull/359)
|
||||||
- Users can now use emails in ACL's groups [#372](https://github.com/juanfont/headscale/issues/372)
|
- Users can now use emails in ACL's groups [#372](https://github.com/juanfont/headscale/issues/372)
|
||||||
- Add shorthand aliases for commands and subcommands [#376](https://github.com/juanfont/headscale/pull/376)
|
- Add shorthand aliases for commands and subcommands [#376](https://github.com/juanfont/headscale/pull/376)
|
||||||
|
- Add `/windows` endpoint for Windows configuration instructions + registry file download [#392](https://github.com/juanfont/headscale/pull/392)
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|
||||||
|
|
4
app.go
4
app.go
|
@ -456,8 +456,10 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine {
|
||||||
router.POST("/machine/:id", h.RegistrationHandler)
|
router.POST("/machine/:id", h.RegistrationHandler)
|
||||||
router.GET("/oidc/register/:mkey", h.RegisterOIDC)
|
router.GET("/oidc/register/:mkey", h.RegisterOIDC)
|
||||||
router.GET("/oidc/callback", h.OIDCCallback)
|
router.GET("/oidc/callback", h.OIDCCallback)
|
||||||
router.GET("/apple", h.AppleMobileConfig)
|
router.GET("/apple", h.AppleConfigMessage)
|
||||||
router.GET("/apple/:platform", h.ApplePlatformConfig)
|
router.GET("/apple/:platform", h.ApplePlatformConfig)
|
||||||
|
router.GET("/windows", h.WindowsConfigMessage)
|
||||||
|
router.GET("/windows/tailscale.reg", h.WindowsRegConfig)
|
||||||
router.GET("/swagger", SwaggerUI)
|
router.GET("/swagger", SwaggerUI)
|
||||||
router.GET("/swagger/v1/openapiv2.json", SwaggerAPIv1)
|
router.GET("/swagger/v1/openapiv2.json", SwaggerAPIv1)
|
||||||
|
|
||||||
|
|
|
@ -11,26 +11,118 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AppleMobileConfig shows a simple message in the browser to point to the CLI
|
// WindowsConfigMessage shows a simple message in the browser for how to configure the Windows Tailscale client.
|
||||||
// Listens in /register.
|
func (h *Headscale) WindowsConfigMessage(ctx *gin.Context) {
|
||||||
func (h *Headscale) AppleMobileConfig(ctx *gin.Context) {
|
winTemplate := template.Must(template.New("windows").Parse(`
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>headscale</h1>
|
||||||
|
<h2>Windows registry configuration</h2>
|
||||||
|
<p>
|
||||||
|
This page provides Windows registry information for the official Windows Tailscale client.
|
||||||
|
<p>
|
||||||
|
<p>
|
||||||
|
The registry file will configure Tailscale to use <code>{{.URL}}</code> as its control server.
|
||||||
|
<p>
|
||||||
|
<h3>Caution</h3>
|
||||||
|
<p>You should always download and inspect the registry file before installing it:</p>
|
||||||
|
<pre><code>curl {{.URL}}/windows/tailscale.reg</code></pre>
|
||||||
|
|
||||||
|
<h2>Installation</h2>
|
||||||
|
<p>Headscale can be set to the default server by running the registry file:</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="/windows/tailscale.reg" download="tailscale.reg">Windows registry file</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>Download the registry file, then run it</li>
|
||||||
|
<li>Follow the prompts</li>
|
||||||
|
<li>Install and run the official windows Tailscale client</li>
|
||||||
|
<li>When the installation has finished, start Tailscale, and log in by clicking the icon in the system tray</li>
|
||||||
|
</ol>
|
||||||
|
<p>Or</p>
|
||||||
|
<p>Open command prompt with Administrator rights. Issue the following commands to add the required registry entries:</p>
|
||||||
|
<pre>
|
||||||
|
<code>REG ADD "HKLM\Software\Tailscale IPN" /v UnattendedMode /t REG_SZ /d always
|
||||||
|
REG ADD "HKLM\Software\Tailscale IPN" /v LoginURL /t REG_SZ /d "{{.URL}}"</code></pre>
|
||||||
|
<p>
|
||||||
|
Restart Tailscale and log in.
|
||||||
|
<p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`))
|
||||||
|
|
||||||
|
config := map[string]interface{}{
|
||||||
|
"URL": h.cfg.ServerURL,
|
||||||
|
}
|
||||||
|
|
||||||
|
var payload bytes.Buffer
|
||||||
|
if err := winTemplate.Execute(&payload, config); err != nil {
|
||||||
|
log.Error().
|
||||||
|
Str("handler", "WindowsRegConfig").
|
||||||
|
Err(err).
|
||||||
|
Msg("Could not render Windows index template")
|
||||||
|
ctx.Data(
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
"text/html; charset=utf-8",
|
||||||
|
[]byte("Could not render Windows index template"),
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Data(http.StatusOK, "text/html; charset=utf-8", payload.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
// WindowsRegConfig generates and serves a .reg file configured with the Headscale server address.
|
||||||
|
func (h *Headscale) WindowsRegConfig(ctx *gin.Context) {
|
||||||
|
config := WindowsRegistryConfig{
|
||||||
|
URL: h.cfg.ServerURL,
|
||||||
|
}
|
||||||
|
|
||||||
|
var content bytes.Buffer
|
||||||
|
if err := windowsRegTemplate.Execute(&content, config); err != nil {
|
||||||
|
log.Error().
|
||||||
|
Str("handler", "WindowsRegConfig").
|
||||||
|
Err(err).
|
||||||
|
Msg("Could not render Apple macOS template")
|
||||||
|
ctx.Data(
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
"text/html; charset=utf-8",
|
||||||
|
[]byte("Could not render Windows registry template"),
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Data(
|
||||||
|
http.StatusOK,
|
||||||
|
"text/x-ms-regedit; charset=utf-8",
|
||||||
|
content.Bytes(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppleConfigMessage shows a simple message in the browser to point the user to the iOS/MacOS profile and instructions for how to install it.
|
||||||
|
func (h *Headscale) AppleConfigMessage(ctx *gin.Context) {
|
||||||
appleTemplate := template.Must(template.New("apple").Parse(`
|
appleTemplate := template.Must(template.New("apple").Parse(`
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<h1>Apple configuration profiles</h1>
|
<h1>headscale</h1>
|
||||||
|
<h2>Apple configuration profiles</h2>
|
||||||
<p>
|
<p>
|
||||||
This page provides <a href="https://support.apple.com/guide/mdm/mdm-overview-mdmbf9e668/web">configuration profiles</a> for the official Tailscale clients for <a href="https://apps.apple.com/us/app/tailscale/id1470499037?ls=1">iOS</a> and <a href="https://apps.apple.com/ca/app/tailscale/id1475387142?mt=12">macOS</a>.
|
This page provides <a href="https://support.apple.com/guide/mdm/mdm-overview-mdmbf9e668/web">configuration profiles</a> for the official Tailscale clients for <a href="https://apps.apple.com/us/app/tailscale/id1470499037?ls=1">iOS</a> and <a href="https://apps.apple.com/ca/app/tailscale/id1475387142?mt=12">macOS</a>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The profiles will configure Tailscale.app to use {{.Url}} as its control server.
|
The profiles will configure Tailscale.app to use <code>{{.URL}}</code> as its control server.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>Caution</h3>
|
<h3>Caution</h3>
|
||||||
<p>You should always inspect the profile before installing it:</p>
|
<p>You should always download and inspect the profile before installing it:</p>
|
||||||
<!--
|
<!--
|
||||||
<p><code>curl {{.Url}}/apple/ios</code></p>
|
<pre><code>curl {{.URL}}/apple/ios</code></pre>
|
||||||
-->
|
-->
|
||||||
<p><code>curl {{.Url}}/apple/macos</code></p>
|
<pre><code>curl {{.URL}}/apple/macos</code></pre>
|
||||||
|
|
||||||
<h2>Profiles</h2>
|
<h2>Profiles</h2>
|
||||||
|
|
||||||
|
@ -192,6 +284,10 @@ func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WindowsRegistryConfig struct {
|
||||||
|
URL string
|
||||||
|
}
|
||||||
|
|
||||||
type AppleMobileConfig struct {
|
type AppleMobileConfig struct {
|
||||||
UUID uuid.UUID
|
UUID uuid.UUID
|
||||||
URL string
|
URL string
|
||||||
|
@ -203,6 +299,14 @@ type AppleMobilePlatformConfig struct {
|
||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var windowsRegTemplate = textTemplate.Must(
|
||||||
|
textTemplate.New("windowsconfig").Parse(`Windows Registry Editor Version 5.00
|
||||||
|
|
||||||
|
[HKEY_LOCAL_MACHINE\SOFTWARE\Tailscale IPN]
|
||||||
|
"UnattendedMode"="always"
|
||||||
|
"LoginURL"="{{.URL}}"
|
||||||
|
`))
|
||||||
|
|
||||||
var commonTemplate = textTemplate.Must(
|
var commonTemplate = textTemplate.Must(
|
||||||
textTemplate.New("mobileconfig").Parse(`<?xml version="1.0" encoding="UTF-8"?>
|
textTemplate.New("mobileconfig").Parse(`<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
Loading…
Reference in a new issue