Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd2e7864a4 | ||
|
|
fec9f6e0e5 | ||
|
|
55fce76a2d | ||
|
|
5fcd6dc5c4 | ||
|
|
3a35e8481a | ||
|
|
a5be653044 | ||
|
|
1d5a262a84 | ||
|
|
ad6fc66875 | ||
|
|
861e9a3193 |
@@ -34,7 +34,7 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: wlan-setup
|
||||
image: gitea.renner.uno/gitea_admin/wlan-setup:2026-11-05-1352 # {"$imagepolicy": "flux-system:wlan-setup"}
|
||||
image: gitea.renner.uno/gitea_admin/wlan-setup:2026-11-05-1517 # {"$imagepolicy": "flux-system:wlan-setup"}
|
||||
env:
|
||||
# Client secret of the "WLAN setup" OAuth2 provider.
|
||||
- name: WLAN_SETUP_CLIENT_SECRET
|
||||
|
||||
@@ -30,7 +30,7 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: controller
|
||||
image: gitea.renner.uno/gitea_admin/kuma-sync:2026-10-30-1314 # {"$imagepolicy": "flux-system:kuma-sync"}
|
||||
image: gitea.renner.uno/gitea_admin/kuma-sync:2026-11-05-1355 # {"$imagepolicy": "flux-system:kuma-sync"}
|
||||
env:
|
||||
- name: KUMA_URL
|
||||
value: https://kuma.renner.uno
|
||||
|
||||
@@ -22,7 +22,7 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: gotenberg
|
||||
image: gotenberg/gotenberg:8.39.0 # {"$imagepolicy": "flux-system:gotenberg"}
|
||||
image: gotenberg/gotenberg:8.40.0 # {"$imagepolicy": "flux-system:gotenberg"}
|
||||
args:
|
||||
- "gotenberg"
|
||||
- "--chromium-disable-javascript=true"
|
||||
|
||||
@@ -155,7 +155,7 @@ spec:
|
||||
# exist on both registries — hence konairius/, which matches the ghcr
|
||||
# namespace. Steady state still pulls from Gitea and never leaves the
|
||||
# network.
|
||||
image: gitea.renner.uno/konairius/alpine-openssl:2026-10-29-1348 # {"$imagepolicy": "flux-system:alpine-openssl"}
|
||||
image: gitea.renner.uno/konairius/alpine-openssl:2026-11-05-1353 # {"$imagepolicy": "flux-system:alpine-openssl"}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
|
||||
@@ -32,7 +32,7 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: backup-verify
|
||||
image: gitea.renner.uno/gitea_admin/ci-backup-verify:2026-10-29 # {"$imagepolicy": "flux-system:backup-verify"}
|
||||
image: gitea.renner.uno/gitea_admin/ci-backup-verify:2026-11-05 # {"$imagepolicy": "flux-system:backup-verify"}
|
||||
command: ["bash", "/script/backup-verify.sh"]
|
||||
env:
|
||||
- name: HOME
|
||||
|
||||
@@ -200,10 +200,10 @@ func addText(parent *etree.Element, tag, ns, text string) *etree.Element {
|
||||
}
|
||||
|
||||
// windowsProfile is the unsigned CarrierProvisioning document: one Hotspot 2.0 WLAN profile
|
||||
// matched by domain name, EAP-TTLS with inner PAP, and the user's credentials. The
|
||||
// CarrierControl WLAN schema allows authentication up to WPA2 (Enterprise); Windows adds the
|
||||
// PMF that the WPA3-Enterprise network requires. Elements follow Microsoft's signed Passpoint
|
||||
// provisioning samples.
|
||||
// (domain and NAI realm renner.uno), WPA3-Enterprise, EAP-TTLS with inner PAP, and the user's
|
||||
// credentials. Valid against the schemas Windows ships in %SYSTEMROOT%\schemas\provisioning
|
||||
// (TestWindowsProfileSchema); SubscriberId is base:SubscriberType, i.e. \w+ and at most 20
|
||||
// characters.
|
||||
func windowsProfile(user, password string) *etree.Document {
|
||||
doc := etree.NewDocument()
|
||||
doc.WriteSettings = etree.WriteSettings{CanonicalEndTags: true, CanonicalText: true, CanonicalAttrVal: true}
|
||||
@@ -213,16 +213,18 @@ func windowsProfile(user, password string) *etree.Document {
|
||||
|
||||
global := add(root, "Global", "")
|
||||
addText(global, "CarrierId", "", carrierID)
|
||||
addText(global, "SubscriberId", "", "renner-unifi")
|
||||
addText(global, "SubscriberId", "", "rennerunifi")
|
||||
|
||||
wlan := add(add(root, "WLANProfiles", ""), "WLANProfile", nsWLAN)
|
||||
addText(wlan, "name", "", "Renner UniFi")
|
||||
addText(add(add(wlan, "SSIDConfig", ""), "SSID", ""), "name", "", "Renner UniFi")
|
||||
addText(add(wlan, "Hotspot2", ""), "DomainName", "", "renner.uno")
|
||||
hotspot2 := add(wlan, "Hotspot2", "")
|
||||
addText(hotspot2, "DomainName", "", "renner.uno")
|
||||
addText(add(hotspot2, "NAIRealm", ""), "name", "", "renner.uno")
|
||||
|
||||
security := add(add(wlan, "MSM", ""), "security", "")
|
||||
auth := add(security, "authEncryption", "")
|
||||
addText(auth, "authentication", "", "WPA2")
|
||||
addText(auth, "authentication", "", "WPA3ENT")
|
||||
addText(auth, "encryption", "", "AES")
|
||||
addText(auth, "useOneX", "", "true")
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"net/textproto"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
@@ -644,6 +645,61 @@ func TestCallbackWindows(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestWindowsProfileSchema validates the signed document with xmllint against the schemas
|
||||
// Windows ships in %SYSTEMROOT%\schemas\provisioning. They are Microsoft's files and not in the
|
||||
// repo: point WLAN_SETUP_PROVISIONING_XSD at a copy of that folder to run it.
|
||||
func TestWindowsProfileSchema(t *testing.T) {
|
||||
dir := os.Getenv("WLAN_SETUP_PROVISIONING_XSD")
|
||||
if dir == "" {
|
||||
t.Skip("WLAN_SETUP_PROVISIONING_XSD not set")
|
||||
}
|
||||
xmllint, err := exec.LookPath("xmllint")
|
||||
if err != nil {
|
||||
t.Skip("xmllint not installed")
|
||||
}
|
||||
tc := writeSigningFiles(t)
|
||||
signer, err := loadSigner(tc.keyFile, tc.certFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
body, err := signer.Sign(windowsProfile("Alice.Smith", testKey))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// The schemas import each other by namespace only; a wrapper schema gives libxml2 the
|
||||
// locations. Dependencies first, so the later imports find their namespaces loaded.
|
||||
wrapper := etree.NewDocument()
|
||||
schema := wrapper.CreateElement("xs:schema")
|
||||
schema.CreateAttr("xmlns:xs", "http://www.w3.org/2001/XMLSchema")
|
||||
schema.CreateAttr("targetNamespace", "urn:wlan-setup:schema-test")
|
||||
for _, s := range []struct{ ns, file string }{
|
||||
{"http://www.microsoft.com/networking/CarrierControl/Base/v1", "provisioning_base_v1.xsd"},
|
||||
{"http://www.microsoft.com/networking/CarrierControl/Plans/v1", "provisioning_plans_v1.xsd"},
|
||||
{"http://www.microsoft.com/networking/CarrierControl/WWAN/v1", "provisioning_wwan_v1.xsd"},
|
||||
{"http://www.microsoft.com/networking/CarrierControl/WLAN/v1", "provisioning_wlan_v1.xsd"},
|
||||
{dsig.Namespace, "provisioning_sig_v1.xsd"},
|
||||
{nsCarrierControl, "provisioning_v1.xsd"},
|
||||
} {
|
||||
imp := schema.CreateElement("xs:import")
|
||||
imp.CreateAttr("namespace", s.ns)
|
||||
imp.CreateAttr("schemaLocation", "file://"+filepath.Join(dir, s.file))
|
||||
}
|
||||
tmp := t.TempDir()
|
||||
wrapperFile := filepath.Join(tmp, "wrapper.xsd")
|
||||
if err := wrapper.WriteToFile(wrapperFile); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
docFile := filepath.Join(tmp, "profile.xml")
|
||||
if err := os.WriteFile(docFile, body, 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out, err := exec.Command(xmllint, "--noout", "--schema", wrapperFile, docFile).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("xmllint: %v\n%s", err, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWindowsProfileDocument(t *testing.T) {
|
||||
tc := writeSigningFiles(t)
|
||||
signer, err := loadSigner(tc.keyFile, tc.certFile)
|
||||
@@ -676,11 +732,12 @@ func TestWindowsProfileDocument(t *testing.T) {
|
||||
)
|
||||
for path, want := range map[string]string{
|
||||
"Global/CarrierId": carrierID,
|
||||
"Global/SubscriberId": "renner-unifi",
|
||||
"Global/SubscriberId": "rennerunifi",
|
||||
wlan + "name": "Renner UniFi",
|
||||
wlan + "SSIDConfig/SSID/name": "Renner UniFi",
|
||||
wlan + "Hotspot2/DomainName": "renner.uno",
|
||||
sec + "authEncryption/authentication": "WPA2",
|
||||
wlan + "Hotspot2/NAIRealm/name": "renner.uno",
|
||||
sec + "authEncryption/authentication": "WPA3ENT",
|
||||
sec + "authEncryption/encryption": "AES",
|
||||
sec + "authEncryption/useOneX": "true",
|
||||
sec + "OneX/authMode": "user",
|
||||
|
||||
Reference in New Issue
Block a user