Преглед на файлове

Added test case for permission policy

Toby Chui преди 9 месеца
родител
ревизия
c1ad36fd18

+ 6 - 0
mod/dynamicproxy/dpcore/dpcore.go

@@ -10,6 +10,8 @@ import (
 	"net/url"
 	"strings"
 	"time"
+
+	"imuslab.com/zoraxy/mod/dynamicproxy/permissionpolicy"
 )
 
 // ReverseProxy is an HTTP Handler that takes an incoming request and
@@ -427,6 +429,10 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr
 	// Copy header from response to client.
 	copyHeader(rw.Header(), res.Header)
 
+	// inject permission policy headers
+	//TODO: Load permission policy from rrr
+	permissionpolicy.InjectPermissionPolicyHeader(rw, nil)
+
 	// The "Trailer" header isn't included in the Transport's response, Build it up from Trailer.
 	if len(res.Trailer) > 0 {
 		trailerKeys := make([]string, 0, len(res.Trailer))

+ 74 - 3
mod/dynamicproxy/permissionpolicy/permissionpolicy.go

@@ -1,6 +1,10 @@
 package permissionpolicy
 
-import "net/http"
+import (
+	"fmt"
+	"net/http"
+	"strings"
+)
 
 /*
 	Permisson Policy
@@ -54,7 +58,74 @@ type PermissionsPolicy struct {
 	VerticalScroll             []string `json:"vertical_scroll"`
 }
 
-func InjectSecurePolicyHeader(w http.ResponseWriter, r *http.Request) {
+// InjectPermissionPolicyHeader inject the permission policy into headers
+func InjectPermissionPolicyHeader(w http.ResponseWriter, policy *PermissionsPolicy) {
+	//Keep the original Permission Policy if exists, or there are no policy given
+	if policy == nil || w.Header().Get("Permissions-Policy") != "" {
+		return
+	}
 
-	//w.Header()
+	policyHeader := []string{}
+
+	// Helper function to add policy directives
+	addDirective := func(name string, sources []string) {
+		if len(sources) > 0 {
+			if sources[0] == "*" {
+				policyHeader = append(policyHeader, fmt.Sprintf("%s=%s", name, "*"))
+			} else {
+				policyHeader = append(policyHeader, fmt.Sprintf("%s=(%s)", name, strings.Join(sources, ", ")))
+			}
+
+		}
+	}
+
+	// Add each policy directive to the header
+	addDirective("accelerometer", policy.Accelerometer)
+	addDirective("ambient-light-sensor", policy.AmbientLightSensor)
+	addDirective("autoplay", policy.Autoplay)
+	addDirective("battery", policy.Battery)
+	addDirective("camera", policy.Camera)
+	addDirective("cross-origin-isolated", policy.CrossOriginIsolated)
+	addDirective("display-capture", policy.DisplayCapture)
+	addDirective("document-domain", policy.DocumentDomain)
+	addDirective("encrypted-media", policy.EncryptedMedia)
+	addDirective("execution-while-not-rendered", policy.ExecutionWhileNotRendered)
+	addDirective("execution-while-out-of-viewport", policy.ExecutionWhileOutOfView)
+	addDirective("fullscreen", policy.Fullscreen)
+	addDirective("geolocation", policy.Geolocation)
+	addDirective("gyroscope", policy.Gyroscope)
+	addDirective("keyboard-map", policy.KeyboardMap)
+	addDirective("magnetometer", policy.Magnetometer)
+	addDirective("microphone", policy.Microphone)
+	addDirective("midi", policy.Midi)
+	addDirective("navigation-override", policy.NavigationOverride)
+	addDirective("payment", policy.Payment)
+	addDirective("picture-in-picture", policy.PictureInPicture)
+	addDirective("publickey-credentials-get", policy.PublicKeyCredentialsGet)
+	addDirective("screen-wake-lock", policy.ScreenWakeLock)
+	addDirective("sync-xhr", policy.SyncXHR)
+	addDirective("usb", policy.USB)
+	addDirective("web-share", policy.WebShare)
+	addDirective("xr-spatial-tracking", policy.XRSpatialTracking)
+	addDirective("clipboard-read", policy.ClipboardRead)
+	addDirective("clipboard-write", policy.ClipboardWrite)
+	addDirective("gamepad", policy.Gamepad)
+	addDirective("speaker-selection", policy.SpeakerSelection)
+	addDirective("conversion-measurement", policy.ConversionMeasurement)
+	addDirective("focus-without-user-activation", policy.FocusWithoutUserActivation)
+	addDirective("hid", policy.HID)
+	addDirective("idle-detection", policy.IdleDetection)
+	addDirective("interest-cohort", policy.InterestCohort)
+	addDirective("serial", policy.Serial)
+	addDirective("sync-script", policy.SyncScript)
+	addDirective("trust-token-redemption", policy.TrustTokenRedemption)
+	addDirective("unload", policy.Unload)
+	addDirective("window-placement", policy.WindowPlacement)
+	addDirective("vertical-scroll", policy.VerticalScroll)
+
+	// Join the directives and set the header
+	policyHeaderValue := strings.Join(policyHeader, ", ")
+
+	//Inject the new policy into the header
+	w.Header().Set("Permissions-Policy", policyHeaderValue)
 }

+ 67 - 0
mod/dynamicproxy/permissionpolicy/permissionpolicy_test.go

@@ -0,0 +1,67 @@
+package permissionpolicy_test
+
+import (
+	"net/http/httptest"
+	"strings"
+	"testing"
+
+	"imuslab.com/zoraxy/mod/dynamicproxy/permissionpolicy"
+)
+
+func TestInjectPermissionPolicyHeader(t *testing.T) {
+	tests := []struct {
+		name           string
+		existingHeader string
+		policy         *permissionpolicy.PermissionsPolicy
+		expectedHeader string
+	}{
+		{
+			name:           "No existing policy, valid PermissionsPolicy",
+			existingHeader: "",
+			policy: &permissionpolicy.PermissionsPolicy{
+				Geolocation: []string{"self"},
+				Microphone:  []string{"https://example.com"},
+				Camera:      []string{"*"},
+			},
+			expectedHeader: "camera=*, geolocation=(self), microphone=(https://example.com)",
+		},
+		{
+			name:           "Existing Permissions-Policy header should not be overwritten",
+			existingHeader: "geolocation=(self), microphone=()",
+			policy: &permissionpolicy.PermissionsPolicy{
+				Geolocation: []string{"self"},
+				Microphone:  []string{"https://example.com"},
+				Camera:      []string{"*"},
+			},
+			expectedHeader: "geolocation=(self), microphone=()",
+		},
+		{
+			name:           "No policy provided",
+			existingHeader: "",
+			policy:         nil,
+			expectedHeader: "",
+		},
+		{
+			name:           "Empty PermissionsPolicy",
+			existingHeader: "",
+			policy:         &permissionpolicy.PermissionsPolicy{},
+			expectedHeader: "",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			rr := httptest.NewRecorder()
+			if tt.existingHeader != "" {
+				rr.Header().Set("Permissions-Policy", tt.existingHeader)
+			}
+
+			permissionpolicy.InjectPermissionPolicyHeader(rr, tt.policy)
+
+			gotHeader := rr.Header().Get("Permissions-Policy")
+			if !strings.Contains(gotHeader, tt.expectedHeader) {
+				t.Errorf("got header %s, want %s", gotHeader, tt.expectedHeader)
+			}
+		})
+	}
+}

+ 1 - 1
tools/provider_config_updater/lego

@@ -1 +1 @@
-Subproject commit 92bde4cd56379551a1ea26354869f98c7b5581ec
+Subproject commit d39d57fbc931ddd6f9f914bc2e245acb0a6c3e43