Skip to content

Commit

Permalink
Fix proxy for image auto (#466)
Browse files Browse the repository at this point in the history
* add tests for proxy use and fix tss.go to use the default transports proxy
Image Auto will respect proxy settings now
  • Loading branch information
danielpaulus authored Aug 18, 2024
1 parent 5403671 commit 27ad5e0
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 12 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ require (
require (
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/elazarl/goproxy v0.0.0-20240726154733-8b0c20506380
github.com/frankban/quicktest v1.14.6 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/btree v1.1.2 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/elazarl/goproxy v0.0.0-20240726154733-8b0c20506380 h1:1NyRx2f4W4WBRyg0Kys0ZbaNmDDzZ2R/C7DTi+bbsJ0=
github.com/elazarl/goproxy v0.0.0-20240726154733-8b0c20506380/go.mod h1:thX175TtLTzLj3p7N/Q9IiKZ7NF+p72cvL91emV0hzo=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
Expand Down
1 change: 1 addition & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Ev
github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
Expand Down
4 changes: 2 additions & 2 deletions ios/imagemounter/imagedownloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func MatchAvailable(version string) string {
return bestMatchString
}

func Download17Plus(device ios.DeviceEntry, baseDir string, version *semver.Version) (string, error) {
func Download17Plus(baseDir string, version *semver.Version) (string, error) {
downloadUrl := fmt.Sprintf("%s%s%s", devicebox, xcode15_4_ddi, ".zip")
log.Infof("device iOS version: %s, getting developer image: %s", version.String(), downloadUrl)

Expand Down Expand Up @@ -158,7 +158,7 @@ func DownloadImageFor(device ios.DeviceEntry, baseDir string) (string, error) {
return "", fmt.Errorf("DownloadImageFor: failed parsing ios productversion: '%s' with %w", allValues.Value.ProductVersion, err)
}
if parsedVersion.GreaterThan(ios.IOS17()) || parsedVersion.Equal(ios.IOS17()) {
return Download17Plus(device, baseDir, parsedVersion)
return Download17Plus(baseDir, parsedVersion)
}
version := MatchAvailable(allValues.Value.ProductVersion)
log.Infof("device iOS version: %s, getting developer image for iOS %s", allValues.Value.ProductVersion, version)
Expand Down
87 changes: 87 additions & 0 deletions ios/imagemounter/imagedownloader_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package imagemounter_test

import (
"fmt"
"log"
"net/http"
"os"
"sync"
"testing"

"github.com/danielpaulus/go-ios/ios"
"github.com/danielpaulus/go-ios/ios/imagemounter"
"github.com/elazarl/goproxy"
"github.com/stretchr/testify/assert"
)

Expand All @@ -17,3 +24,83 @@ func TestVersionMatching(t *testing.T) {
assert.Equal(t, "15.7", imagemounter.MatchAvailable("15.7.2"))
assert.Equal(t, "16.6", imagemounter.MatchAvailable("19.4.1"))
}

func TestUsesProxy(t *testing.T) {
proxy := goproxy.NewProxyHttpServer()
proxy.Verbose = true
wg := sync.WaitGroup{}
wg.Add(1)

proxy.OnRequest().HandleConnectFunc(func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
log.Printf("Got request for %s", host)
wg.Done()
return goproxy.OkConnect, host
})

go func() {
log.Print(http.ListenAndServe(":60001", proxy))
}()
tempDir, err := os.MkdirTemp("", "example")
if err != nil {
fmt.Printf("Error creating temporary directory: %v\n", err)
t.Fail()
return
}
defer os.RemoveAll(tempDir)
ios.UseHttpProxy("http://localhost:60001")
path, err := imagemounter.Download17Plus(tempDir, ios.IOS17())
if !assert.Nil(t, err) {
t.Fail()
}
log.Printf("Downloaded to %s", path)
wg.Wait()
d, _ := ios.ListDevices()
if len(d.DeviceList) == 0 {
t.Skip("No device attached")
return
}
wg.Add(1)
m, err := imagemounter.NewPersonalizedDeveloperDiskImageMounter(d.DeviceList[0], ios.IOS17())
if !assert.Nil(t, err) {
t.Fail()
}

err = m.MountImage(path)
if !assert.Nil(t, err) {
t.Fail()
}
wg.Wait()
//mounter.MountImage(path)
}

func TestWorksWithoutProxy(t *testing.T) {

tempDir, err := os.MkdirTemp("", "example")
if err != nil {
fmt.Printf("Error creating temporary directory: %v\n", err)
return
}
defer os.RemoveAll(tempDir)
ios.UseHttpProxy("")
path, err := imagemounter.Download17Plus(tempDir, ios.IOS17())
if !assert.Nil(t, err) {
t.Fail()
}
log.Printf("Downloaded to %s", path)

d, _ := ios.ListDevices()
if len(d.DeviceList) == 0 {
t.Skip("No device attached")
return
}
m, err := imagemounter.NewPersonalizedDeveloperDiskImageMounter(d.DeviceList[0], ios.IOS17())
if !assert.Nil(t, err) {
t.Fail()
}

err = m.MountImage(path)
if !assert.Nil(t, err) {
t.Fail()
}

}
2 changes: 2 additions & 0 deletions ios/imagemounter/tss.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,13 @@ func (t tssClient) getSignature(identity buildIdentity, identifiers personalizat
if err != nil {
return nil, fmt.Errorf("getSignature: failed to encode request body: %w", err)
}

h := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
Proxy: t.h.Transport.(*http.Transport).Proxy,
},
Timeout: 1 * time.Minute,
}
Expand Down
31 changes: 31 additions & 0 deletions ios/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"errors"
"fmt"
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"runtime"
Expand All @@ -17,6 +19,35 @@ import (
plist "howett.net/plist"
)

// UseHttpProxy sets the default http transport to use the given proxy url.
// If the proxyUrl is empty, it will try to use the HTTP_PROXY or HTTPS_PROXY environment variables.
// If the environment variables are not set, it will not set a proxy.
// If the proxyUrl is invalid, it will return an error.
func UseHttpProxy(proxyUrl string) error {
if proxyUrl != "" {
parsedUrl, err := url.Parse(proxyUrl)
if err != nil {
return fmt.Errorf("could not parse proxy url %s: %v", proxyUrl, err)
}
http.DefaultTransport = &http.Transport{Proxy: http.ProxyURL(parsedUrl)}
return nil
}

proxyUrl = os.Getenv("HTTP_PROXY")
if os.Getenv("HTTPS_PROXY") != "" {
proxyUrl = os.Getenv("HTTPS_PROXY")
}

if proxyUrl != "" {
parsedUrl, err := url.Parse(proxyUrl)
if err != nil {
return fmt.Errorf("could not parse proxy url %s: %v", proxyUrl, err)
}
http.DefaultTransport = &http.Transport{Proxy: http.ProxyURL(parsedUrl)}
}
return nil
}

// CheckRoot checks if the current user is root or has elevated privileges on Windows.
func CheckRoot() error {
// On Windows, check if the process has elevated privileges
Expand Down
77 changes: 77 additions & 0 deletions ios/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package ios_test

import (
"flag"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
Expand All @@ -24,6 +26,81 @@ type SampleData struct {
FloatValue float64
}

func TestUseHttpProxy(t *testing.T) {
tests := []struct {
name string
proxyUrl string
envProxy string
envHttps string
expectErr bool
}{
{
name: "Valid proxy URL",
proxyUrl: "http://test:[email protected]:8080",
expectErr: false,
},
{
name: "Invalid proxy URL",
proxyUrl: "http://proxy:invalid",
expectErr: true,
},
{
name: "Empty proxy URL with valid HTTP_PROXY env",
proxyUrl: "",
envProxy: "http://proxy.example.com:8080",
expectErr: false,
},
{
name: "Empty proxy URL with valid HTTPS_PROXY env",
proxyUrl: "",
envHttps: "http://proxy.example.com:8080",
expectErr: false,
},
{
name: "Empty proxy URL with invalid HTTP_PROXY env",
proxyUrl: "",
envProxy: "http://proxy:invalid",
expectErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Set environment variables
if tt.envProxy != "" {
os.Setenv("HTTP_PROXY", tt.envProxy)
defer os.Unsetenv("HTTP_PROXY")
}
if tt.envHttps != "" {
os.Setenv("HTTPS_PROXY", tt.envHttps)
defer os.Unsetenv("HTTPS_PROXY")
}

err := ios.UseHttpProxy(tt.proxyUrl)
if (err != nil) != tt.expectErr {
t.Errorf("UseHttpProxy() error = %v, expectErr %v", err, tt.expectErr)
}

if !tt.expectErr {
parsedUrl, _ := url.Parse(tt.proxyUrl)
if tt.proxyUrl == "" {
if tt.envHttps != "" {
parsedUrl, _ = url.Parse(tt.envHttps)
} else if tt.envProxy != "" {
parsedUrl, _ = url.Parse(tt.envProxy)
}
}
proxyFunc := http.DefaultTransport.(*http.Transport).Proxy
req, _ := http.NewRequest("GET", "http://example.com", nil)
proxyUrl, err := proxyFunc(req)
if err != nil || proxyUrl.String() != parsedUrl.String() {
t.Errorf("Expected proxy URL %v, got %v", parsedUrl, proxyUrl)
}
}
})
}
}

func TestGenericSliceToType(t *testing.T) {
slice := []interface{}{5, 3, 2}
v, err := ios.GenericSliceToType[int](slice)
Expand Down
11 changes: 1 addition & 10 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"os/signal"
"path"
Expand Down Expand Up @@ -296,14 +294,7 @@ The commands work as following:
return
}
proxyUrl, _ := arguments.String("--proxyurl")
if proxyUrl == "" {
proxyUrl = os.Getenv("HTTP_PROXY")
}
if proxyUrl != "" {
parsedUrl, err := url.Parse(proxyUrl)
exitIfError("failed parsing proxy url", err)
http.DefaultTransport = &http.Transport{Proxy: http.ProxyURL(parsedUrl)}
}
exitIfError("could not parse proxy url", ios.UseHttpProxy(proxyUrl))

b, _ := arguments.Bool("listen")
if b {
Expand Down

0 comments on commit 27ad5e0

Please sign in to comment.