mirror of
https://github.com/juanfont/headscale.git
synced 2025-02-08 10:18:01 +09:00
cd3b8e68ff
Some checks are pending
Build / build-nix (push) Waiting to run
Build / build-cross (GOARCH=386 GOOS=linux) (push) Waiting to run
Build / build-cross (GOARCH=amd64 GOOS=darwin) (push) Waiting to run
Build / build-cross (GOARCH=amd64 GOOS=linux) (push) Waiting to run
Build / build-cross (GOARCH=arm GOOS=linux GOARM=5) (push) Waiting to run
Build / build-cross (GOARCH=arm GOOS=linux GOARM=6) (push) Waiting to run
Build / build-cross (GOARCH=arm GOOS=linux GOARM=7) (push) Waiting to run
Build / build-cross (GOARCH=arm64 GOOS=darwin) (push) Waiting to run
Build / build-cross (GOARCH=arm64 GOOS=linux) (push) Waiting to run
Tests / test (push) Waiting to run
* clean up handler methods, common logging Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * streamline http.Error calls Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> --------- Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
192 lines
5.4 KiB
Go
192 lines
5.4 KiB
Go
package hscontrol
|
|
|
|
import (
|
|
"bytes"
|
|
_ "embed"
|
|
"html/template"
|
|
"net/http"
|
|
textTemplate "text/template"
|
|
|
|
"github.com/gofrs/uuid/v5"
|
|
"github.com/gorilla/mux"
|
|
"github.com/juanfont/headscale/hscontrol/templates"
|
|
)
|
|
|
|
// WindowsConfigMessage shows a simple message in the browser for how to configure the Windows Tailscale client.
|
|
func (h *Headscale) WindowsConfigMessage(
|
|
writer http.ResponseWriter,
|
|
req *http.Request,
|
|
) {
|
|
writer.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
writer.WriteHeader(http.StatusOK)
|
|
writer.Write([]byte(templates.Windows(h.cfg.ServerURL).Render()))
|
|
}
|
|
|
|
// 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(
|
|
writer http.ResponseWriter,
|
|
req *http.Request,
|
|
) {
|
|
writer.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
writer.WriteHeader(http.StatusOK)
|
|
writer.Write([]byte(templates.Apple(h.cfg.ServerURL).Render()))
|
|
}
|
|
|
|
func (h *Headscale) ApplePlatformConfig(
|
|
writer http.ResponseWriter,
|
|
req *http.Request,
|
|
) {
|
|
vars := mux.Vars(req)
|
|
platform, ok := vars["platform"]
|
|
if !ok {
|
|
httpError(writer, nil, "No platform specified", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
id, err := uuid.NewV4()
|
|
if err != nil {
|
|
httpError(writer, nil, "Failed to create UUID", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
contentID, err := uuid.NewV4()
|
|
if err != nil {
|
|
httpError(writer, nil, "Failed to create UUID", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
platformConfig := AppleMobilePlatformConfig{
|
|
UUID: contentID,
|
|
URL: h.cfg.ServerURL,
|
|
}
|
|
|
|
var payload bytes.Buffer
|
|
|
|
switch platform {
|
|
case "macos-standalone":
|
|
if err := macosStandaloneTemplate.Execute(&payload, platformConfig); err != nil {
|
|
httpError(writer, err, "Could not render Apple macOS template", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
case "macos-app-store":
|
|
if err := macosAppStoreTemplate.Execute(&payload, platformConfig); err != nil {
|
|
httpError(writer, err, "Could not render Apple macOS template", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
case "ios":
|
|
if err := iosTemplate.Execute(&payload, platformConfig); err != nil {
|
|
httpError(writer, err, "Could not render Apple iOS template", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
default:
|
|
httpError(writer, err, "Invalid platform. Only ios, macos-app-store and macos-standalone are supported", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
config := AppleMobileConfig{
|
|
UUID: id,
|
|
URL: h.cfg.ServerURL,
|
|
Payload: payload.String(),
|
|
}
|
|
|
|
var content bytes.Buffer
|
|
if err := commonTemplate.Execute(&content, config); err != nil {
|
|
httpError(writer, err, "Could not render platform iOS template", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
writer.Header().
|
|
Set("Content-Type", "application/x-apple-aspen-config; charset=utf-8")
|
|
writer.WriteHeader(http.StatusOK)
|
|
writer.Write(content.Bytes())
|
|
}
|
|
|
|
type AppleMobileConfig struct {
|
|
UUID uuid.UUID
|
|
URL string
|
|
Payload string
|
|
}
|
|
|
|
type AppleMobilePlatformConfig struct {
|
|
UUID uuid.UUID
|
|
URL string
|
|
}
|
|
|
|
var commonTemplate = textTemplate.Must(
|
|
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">
|
|
<plist version="1.0">
|
|
<dict>
|
|
<key>PayloadUUID</key>
|
|
<string>{{.UUID}}</string>
|
|
<key>PayloadDisplayName</key>
|
|
<string>Headscale</string>
|
|
<key>PayloadDescription</key>
|
|
<string>Configure Tailscale login server to: {{.URL}}</string>
|
|
<key>PayloadIdentifier</key>
|
|
<string>com.github.juanfont.headscale</string>
|
|
<key>PayloadRemovalDisallowed</key>
|
|
<false/>
|
|
<key>PayloadType</key>
|
|
<string>Configuration</string>
|
|
<key>PayloadVersion</key>
|
|
<integer>1</integer>
|
|
<key>PayloadContent</key>
|
|
<array>
|
|
{{.Payload}}
|
|
</array>
|
|
</dict>
|
|
</plist>`),
|
|
)
|
|
|
|
var iosTemplate = textTemplate.Must(textTemplate.New("iosTemplate").Parse(`
|
|
<dict>
|
|
<key>PayloadType</key>
|
|
<string>io.tailscale.ipn.ios</string>
|
|
<key>PayloadUUID</key>
|
|
<string>{{.UUID}}</string>
|
|
<key>PayloadIdentifier</key>
|
|
<string>com.github.juanfont.headscale</string>
|
|
<key>PayloadVersion</key>
|
|
<integer>1</integer>
|
|
<key>PayloadEnabled</key>
|
|
<true/>
|
|
|
|
<key>ControlURL</key>
|
|
<string>{{.URL}}</string>
|
|
</dict>
|
|
`))
|
|
|
|
var macosAppStoreTemplate = template.Must(template.New("macosTemplate").Parse(`
|
|
<dict>
|
|
<key>PayloadType</key>
|
|
<string>io.tailscale.ipn.macos</string>
|
|
<key>PayloadUUID</key>
|
|
<string>{{.UUID}}</string>
|
|
<key>PayloadIdentifier</key>
|
|
<string>com.github.juanfont.headscale</string>
|
|
<key>PayloadVersion</key>
|
|
<integer>1</integer>
|
|
<key>PayloadEnabled</key>
|
|
<true/>
|
|
<key>ControlURL</key>
|
|
<string>{{.URL}}</string>
|
|
</dict>
|
|
`))
|
|
|
|
var macosStandaloneTemplate = template.Must(template.New("macosStandaloneTemplate").Parse(`
|
|
<dict>
|
|
<key>PayloadType</key>
|
|
<string>io.tailscale.ipn.macsys</string>
|
|
<key>PayloadUUID</key>
|
|
<string>{{.UUID}}</string>
|
|
<key>PayloadIdentifier</key>
|
|
<string>com.github.juanfont.headscale</string>
|
|
<key>PayloadVersion</key>
|
|
<integer>1</integer>
|
|
<key>PayloadEnabled</key>
|
|
<true/>
|
|
<key>ControlURL</key>
|
|
<string>{{.URL}}</string>
|
|
</dict>
|
|
`))
|