diff --git a/go.mod b/go.mod index 3ac221ac..8a1a93c8 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/ebitengine/purego v0.10.2 github.com/go-compressions/lzfse v0.3.0 github.com/juju/persistent-cookiejar v1.0.0 - github.com/klauspost/compress v1.18.6 + github.com/klauspost/compress v1.18.7 github.com/majd/go-apfs v1.0.29 github.com/modelcontextprotocol/go-sdk v1.8.0 github.com/onsi/ginkgo/v2 v2.5.0 diff --git a/go.sum b/go.sum index ffa956a4..0318716f 100644 --- a/go.sum +++ b/go.sum @@ -108,8 +108,8 @@ github.com/juju/go4 v0.0.0-20160222163258-40d72ab9641a h1:45JtCyuNYE+QN9aPuR1ID9 github.com/juju/go4 v0.0.0-20160222163258-40d72ab9641a/go.mod h1:RVHtZuvrpETIepiNUrNlih2OynoFf1eM6DGC6dloXzk= github.com/juju/persistent-cookiejar v1.0.0 h1:Ag7+QLzqC2m+OYXy2QQnRjb3gTkEBSZagZ6QozwT3EQ= github.com/juju/persistent-cookiejar v1.0.0/go.mod h1:zrbmo4nBKaiP/Ez3F67ewkMbzGYfXyMvRtbOfuAwG0w= -github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao= -github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= +github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= diff --git a/internal/sap/signer_integration_test.go b/internal/sap/signer_integration_test.go index ed6665a5..cb2f9c16 100644 --- a/internal/sap/signer_integration_test.go +++ b/internal/sap/signer_integration_test.go @@ -1,47 +1,55 @@ package sap import ( - "bytes" "context" + "errors" + "net" "testing" "time" + + "github.com/avast/retry-go" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" ) func TestSignerIntegration(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) - defer cancel() - - signer, err := NewSigner(ctx, Config{ - SetupURL: "https://fpinit.itunes.apple.com/v1/signSapSetup/legacy", - CertificateURL: "https://s.mzstatic.com/sap/setupCert.plist", - Version: 200, - HardwareID: []byte{0x02, 0, 0, 0, 0, 1}, - }) - if err != nil { - t.Fatal(err) - } - - t.Cleanup(func() { - if err := signer.Close(); err != nil { - t.Errorf("close signer: %v", err) - } - }) - - signature, err := signer.Sign([]byte("ipatool SAP smoke test")) - if err != nil { - t.Fatal(err) - } - - if len(signature) == 0 { - t.Fatal("signature is empty") - } - - second, err := signer.Sign([]byte("ipatool second SAP smoke test")) - if err != nil { - t.Fatal(err) - } - - if len(second) == 0 || bytes.Equal(signature, second) { - t.Fatal("second signature is empty or unexpectedly reused") - } + RegisterFailHandler(Fail) + RunSpecs(t, "SAP Signer Integration Suite") } + +var _ = Describe("SAP signer integration", func() { + It("signs distinct payloads with distinct signatures", func() { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancel() + + var signer ActionSigner + + // Retry live endpoint timeouts with a fresh session, within the overall deadline. + err := retry.Do(func() error { + var err error + signer, err = NewSigner(ctx, Config{ + SetupURL: "https://fpinit.itunes.apple.com/v1/signSapSetup/legacy", + CertificateURL: "https://s.mzstatic.com/sap/setupCert.plist", + Version: 200, + HardwareID: []byte{0x02, 0, 0, 0, 0, 1}, + }) + + return err + }, retry.Context(ctx), retry.Attempts(3), retry.RetryIf(func(err error) bool { + var networkError net.Error + + return errors.As(err, &networkError) && networkError.Timeout() + })) + Expect(err).NotTo(HaveOccurred()) + DeferCleanup(signer.Close) + + signature, err := signer.Sign([]byte("ipatool SAP smoke test")) + Expect(err).NotTo(HaveOccurred()) + Expect(signature).NotTo(BeEmpty()) + + second, err := signer.Sign([]byte("ipatool second SAP smoke test")) + Expect(err).NotTo(HaveOccurred()) + Expect(second).NotTo(BeEmpty()) + Expect(second).NotTo(Equal(signature)) + }) +})