Skip to content

Commit e6b7808

Browse files
lpusoktothszabiofalvai
authored
[STEP-2061] Enterprise api (#246)
* Added enterprise API client * Added test * Make baseURL fully overrideable * Use the new API flag * Update input override * Update appstoreconnect.go * Update URL creation * Added codesigning integration test * Add enterprise flag * Use the new v2 devportalservice. Moved appleauth.Credentials to devportalservice.Credentials. * Use new devportalservice.NewBitriseClient with new params * Added codesinging e2e tests using dev step * Disable Xcode managed signing for enterpries as not working yet * lint * Change workdir back * lint * yml formatting * Speed up spaceships tests by removing sleep in tests * Fix dev step path * Convert e2e test step to scrip to work around go workspace issues due to CLI copying step dir * step path lookup fix * E2E test step path fixed * Removed e2e from legacy WF * Deduplicate legacy WF * Fix step ref * Lint * Revert E2E test changes for now --------- Co-authored-by: Szabolcs Toth <54896607+tothszabi@users.noreply.github.com> Co-authored-by: Olivér Falvai <ofalvai@gmail.com>
1 parent a05d0b4 commit e6b7808

27 files changed

+211
-113
lines changed

autocodesign/autocodesign.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import (
1111

1212
"github.com/bitrise-io/go-utils/log"
1313
"github.com/bitrise-io/go-xcode/certificateutil"
14-
"github.com/bitrise-io/go-xcode/devportalservice"
1514
"github.com/bitrise-io/go-xcode/profileutil"
1615
"github.com/bitrise-io/go-xcode/v2/autocodesign/devportalclient/appstoreconnect"
16+
"github.com/bitrise-io/go-xcode/v2/devportalservice"
1717
"github.com/bitrise-io/go-xcode/xcodeproject/serialized"
1818
)
1919

autocodesign/devices.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import (
55
"fmt"
66

77
"github.com/bitrise-io/go-utils/log"
8-
"github.com/bitrise-io/go-xcode/devportalservice"
98
"github.com/bitrise-io/go-xcode/v2/autocodesign/devportalclient/appstoreconnect"
9+
"github.com/bitrise-io/go-xcode/v2/devportalservice"
1010
)
1111

1212
// EnsureTestDevices fetches devices from Apple, and register missing devices.

autocodesign/devices_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import (
44
"fmt"
55
"testing"
66

7-
"github.com/bitrise-io/go-xcode/devportalservice"
87
"github.com/bitrise-io/go-xcode/v2/autocodesign/devportalclient/appstoreconnect"
8+
"github.com/bitrise-io/go-xcode/v2/devportalservice"
99
"github.com/stretchr/testify/assert"
1010
"github.com/stretchr/testify/require"
1111
)

autocodesign/devportalclient/appstoreconnect/appstoreconnect.go

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"net/http"
1313
"net/url"
1414
"reflect"
15+
"strings"
1516
"time"
1617

1718
"github.com/bitrise-io/go-utils/httputil"
@@ -23,7 +24,12 @@ import (
2324
)
2425

2526
const (
26-
baseURL = "https://api.appstoreconnect.apple.com/"
27+
clientBaseURL = "https://api.appstoreconnect.apple.com/"
28+
tokenAudience = "appstoreconnect-v1"
29+
30+
clientBaseEnterpiseURL = "https://api.enterprise.developer.apple.com/"
31+
tokenEnterpriseAudience = "apple-developer-enterprise-v1"
32+
2733
apiVersion = "v1"
2834
)
2935

@@ -52,6 +58,7 @@ type Client struct {
5258
keyID string
5359
issuerID string
5460
privateKeyContent []byte
61+
audience string
5562

5663
token *jwt.Token
5764
signedToken string
@@ -83,8 +90,15 @@ func NewRetryableHTTPClient() *http.Client {
8390
}
8491

8592
// NewClient creates a new client
86-
func NewClient(httpClient HTTPClient, keyID, issuerID string, privateKey []byte) *Client {
87-
baseURL, err := url.Parse(baseURL)
93+
func NewClient(httpClient HTTPClient, keyID, issuerID string, privateKey []byte, isEnterpise bool) *Client {
94+
targetURL := clientBaseURL
95+
targetAudience := tokenAudience
96+
if isEnterpise {
97+
targetURL = clientBaseEnterpiseURL
98+
targetAudience = tokenEnterpriseAudience
99+
}
100+
101+
baseURL, err := url.Parse(targetURL)
88102
if err != nil {
89103
panic("invalid api base url: " + err.Error())
90104
}
@@ -93,6 +107,7 @@ func NewClient(httpClient HTTPClient, keyID, issuerID string, privateKey []byte)
93107
keyID: keyID,
94108
issuerID: issuerID,
95109
privateKeyContent: privateKey,
110+
audience: targetAudience,
96111

97112
client: httpClient,
98113
BaseURL: baseURL,
@@ -126,17 +141,29 @@ func (c *Client) ensureSignedToken() (string, error) {
126141
log.Debugf("Generating JWT token")
127142
}
128143

129-
c.token = createToken(c.keyID, c.issuerID)
144+
c.token = createToken(c.keyID, c.issuerID, c.audience)
130145
var err error
131146
if c.signedToken, err = signToken(c.token, c.privateKeyContent); err != nil {
132147
return "", err
133148
}
134149
return c.signedToken, nil
135150
}
136151

152+
// NewRequestWithRelationshipURL ...
153+
func (c *Client) NewRequestWithRelationshipURL(method, endpoint string, body interface{}) (*http.Request, error) {
154+
endpoint = strings.TrimPrefix(endpoint, c.BaseURL.String()+apiVersion+"/")
155+
156+
return c.NewRequest(method, endpoint, body)
157+
}
158+
137159
// NewRequest creates a new http.Request
138160
func (c *Client) NewRequest(method, endpoint string, body interface{}) (*http.Request, error) {
139161
endpoint = apiVersion + "/" + endpoint
162+
163+
return c.newRequest(method, endpoint, body)
164+
}
165+
166+
func (c *Client) newRequest(method, endpoint string, body interface{}) (*http.Request, error) {
140167
u, err := c.BaseURL.Parse(endpoint)
141168
if err != nil {
142169
return nil, fmt.Errorf("parsing endpoint failed: %v", err)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Package appstoreconnect implements a client for the App Store Connect API.
2+
//
3+
// It contains type definitions, authentication and API calls, without business logic built on those API calls.
4+
package appstoreconnect
5+
6+
import (
7+
"net/url"
8+
"testing"
9+
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestNewClient(t *testing.T) {
14+
got := NewClient(NewRetryableHTTPClient(), "keyID", "issuerID", []byte{}, false)
15+
16+
require.Equal(t, "appstoreconnect-v1", got.audience)
17+
18+
wantURL, err := url.Parse("https://api.appstoreconnect.apple.com/")
19+
require.NoError(t, err)
20+
require.Equal(t, wantURL, got.BaseURL)
21+
}
22+
23+
func TestNewEnterpriseClient(t *testing.T) {
24+
got := NewClient(NewRetryableHTTPClient(), "keyID", "issuerID", []byte{}, true)
25+
26+
require.Equal(t, "apple-developer-enterprise-v1", got.audience)
27+
28+
wantURL, err := url.Parse("https://api.enterprise.developer.apple.com/")
29+
require.NoError(t, err)
30+
require.Equal(t, wantURL, got.BaseURL)
31+
}

autocodesign/devportalclient/appstoreconnect/bundleids.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package appstoreconnect
22

33
import (
44
"net/http"
5-
"strings"
65
)
76

87
// BundleIDsEndpoint ...
@@ -125,8 +124,7 @@ func (s ProvisioningService) CreateBundleID(body BundleIDCreateRequest) (*Bundle
125124

126125
// BundleID ...
127126
func (s ProvisioningService) BundleID(relationshipLink string) (*BundleIDResponse, error) {
128-
endpoint := strings.TrimPrefix(relationshipLink, baseURL+apiVersion)
129-
req, err := s.client.NewRequest(http.MethodGet, endpoint, nil)
127+
req, err := s.client.NewRequestWithRelationshipURL(http.MethodGet, relationshipLink, nil)
130128
if err != nil {
131129
return nil, err
132130
}

autocodesign/devportalclient/appstoreconnect/capabilities.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package appstoreconnect
22

33
import (
44
"net/http"
5-
"strings"
65
)
76

87
// BundleIDCapabilitiesEndpoint ...
@@ -262,8 +261,7 @@ func (s ProvisioningService) UpdateCapability(id string, body BundleIDCapability
262261

263262
// Capabilities ...
264263
func (s ProvisioningService) Capabilities(relationshipLink string) (*BundleIDCapabilitiesResponse, error) {
265-
endpoint := strings.TrimPrefix(relationshipLink, baseURL+apiVersion)
266-
req, err := s.client.NewRequest(http.MethodGet, endpoint, nil)
264+
req, err := s.client.NewRequestWithRelationshipURL(http.MethodGet, relationshipLink, nil)
267265
if err != nil {
268266
return nil, err
269267
}

autocodesign/devportalclient/appstoreconnect/certificates.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package appstoreconnect
33
import (
44
"fmt"
55
"net/http"
6-
"strings"
76
)
87

98
// CertificatesEndpoint ...
@@ -108,8 +107,7 @@ func (s ProvisioningService) Certificates(relationshipLink string, opt *PagingOp
108107
return nil, err
109108
}
110109

111-
endpoint := strings.TrimPrefix(u, baseURL+apiVersion)
112-
req, err := s.client.NewRequest(http.MethodGet, endpoint, nil)
110+
req, err := s.client.NewRequestWithRelationshipURL(http.MethodGet, u, nil)
113111
if err != nil {
114112
return nil, err
115113
}

autocodesign/devportalclient/appstoreconnect/devices.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package appstoreconnect
22

33
import (
44
"net/http"
5-
"strings"
65
)
76

87
// DevicesEndpoint ...
@@ -145,8 +144,7 @@ func (s ProvisioningService) Devices(relationshipLink string, opt *PagingOptions
145144
return nil, err
146145
}
147146

148-
endpoint := strings.TrimPrefix(u, baseURL+apiVersion)
149-
req, err := s.client.NewRequest(http.MethodGet, endpoint, nil)
147+
req, err := s.client.NewRequestWithRelationshipURL(http.MethodGet, u, nil)
150148
if err != nil {
151149
return nil, err
152150
}

autocodesign/devportalclient/appstoreconnect/jwt.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ func signToken(token *jwt.Token, privateKeyContent []byte) (string, error) {
3131
}
3232

3333
// createToken creates a jwt.Token for the Apple API
34-
func createToken(keyID string, issuerID string) *jwt.Token {
34+
func createToken(keyID string, issuerID string, audience string) *jwt.Token {
3535
payload := claims{
3636
IssuerID: issuerID,
3737
Expiration: time.Now().Add(jwtDuration).Unix(),
38-
Audience: "appstoreconnect-v1",
38+
Audience: audience,
3939
}
4040

4141
// registers headers: alg = ES256 and typ = JWT

0 commit comments

Comments
 (0)