Skip to content

Commit 4a4d938

Browse files
adborbaslpusok
andauthored
Use app specific password from Apple ID connection (#102)
* Use FileProvider from input package * Get app_specific_password from connection * fix invalid bitrise.yml * Use conn's appspecpass everywhere * Connection nil check * improve test workflow naming * Input provided password overwrites connection provided password * Handle password from input and connection correctly * Update step.yml * Update appleauth/auth_source.go Co-authored-by: lpusok <[email protected]> * Use connection password for ConnectionAppleIDFastlaneSource * Update step.yml * Update connection input description Co-authored-by: lpusok <[email protected]>
1 parent c55aafe commit 4a4d938

File tree

13 files changed

+626
-255
lines changed

13 files changed

+626
-255
lines changed

appleauth/auth_source.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func (*ConnectionAppleIDSource) Fetch(conn *devportalservice.AppleDeveloperConne
9595
Username: conn.AppleIDConnection.AppleID,
9696
Password: conn.AppleIDConnection.Password,
9797
Session: "",
98-
AppSpecificPassword: inputs.AppSpecificPassword,
98+
AppSpecificPassword: appSpecificPasswordFavouringConnection(conn.AppleIDConnection, inputs.AppSpecificPassword),
9999
},
100100
}, nil
101101
}
@@ -149,7 +149,7 @@ func (*ConnectionAppleIDFastlaneSource) Fetch(conn *devportalservice.AppleDevelo
149149
Username: conn.AppleIDConnection.AppleID,
150150
Password: conn.AppleIDConnection.Password,
151151
Session: session,
152-
AppSpecificPassword: inputs.AppSpecificPassword,
152+
AppSpecificPassword: appSpecificPasswordFavouringConnection(conn.AppleIDConnection, inputs.AppSpecificPassword),
153153
},
154154
}, nil
155155
}
@@ -175,3 +175,14 @@ func (*InputAppleIDFastlaneSource) Fetch(conn *devportalservice.AppleDeveloperCo
175175
},
176176
}, nil
177177
}
178+
179+
func appSpecificPasswordFavouringConnection(conn *devportalservice.AppleIDConnection, passwordFromInput string) string {
180+
appSpecificPassword := passwordFromInput
181+
182+
// AppSpecifcPassword from the connection overwrites the one from the input
183+
if conn != nil && conn.AppSpecificPassword != "" {
184+
appSpecificPassword = conn.AppSpecificPassword
185+
}
186+
187+
return appSpecificPassword
188+
}

appleauth/fetch_test.go

Lines changed: 122 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,47 @@ import (
88
"github.com/stretchr/testify/require"
99
)
1010

11+
var (
12+
argInput = Inputs{
13+
Username: "input_username", Password: "input_password", AppSpecificPassword: "input_appspecificpassword",
14+
APIIssuer: "", APIKeyPath: "",
15+
}
16+
17+
argAppleIDConnection = devportalservice.AppleIDConnection{
18+
AppleID: "connection_appleid", Password: "connection_password", AppSpecificPassword: "connection_appspecificpassword",
19+
}
20+
21+
argAppleIDConnectionMissingPassword = devportalservice.AppleIDConnection{
22+
AppleID: "connection_appleid", Password: "connection_password", AppSpecificPassword: "",
23+
}
24+
25+
argAPIKeyConnection = devportalservice.APIKeyConnection{
26+
KeyID: "keyconnection_keyID", IssuerID: "keyconnection_issuerID", PrivateKey: "keyconnection_PrivateKey",
27+
}
28+
)
29+
30+
var (
31+
expectedAppleIDWithArgInput = AppleID{
32+
Username: argInput.Username,
33+
Password: argInput.Password,
34+
AppSpecificPassword: argInput.AppSpecificPassword,
35+
Session: "",
36+
}
37+
38+
expectedAppleIDWithArgConnection = AppleID{
39+
Username: argAppleIDConnection.AppleID,
40+
Password: argAppleIDConnection.Password,
41+
AppSpecificPassword: argAppleIDConnection.AppSpecificPassword,
42+
Session: "",
43+
}
44+
45+
expectedAppleIDWithAPIKeyConnection = devportalservice.APIKeyConnection{
46+
KeyID: argAPIKeyConnection.KeyID,
47+
IssuerID: argAPIKeyConnection.IssuerID,
48+
PrivateKey: argAPIKeyConnection.PrivateKey,
49+
}
50+
)
51+
1152
func TestSelect(t *testing.T) {
1253
type args struct {
1354
devportalConnection *devportalservice.AppleDeveloperConnection
@@ -48,58 +89,114 @@ func TestSelect(t *testing.T) {
4889
args: args{
4990
devportalConnection: &devportalservice.AppleDeveloperConnection{},
5091
authSources: []Source{&ConnectionAPIKeySource{}, &ConnectionAppleIDSource{}, &InputAPIKeySource{}, &InputAppleIDSource{}},
51-
inputs: Inputs{
52-
Username: "a", Password: "b", AppSpecificPassword: "c",
53-
APIIssuer: "", APIKeyPath: "",
92+
inputs: argInput,
93+
},
94+
want: Credentials{
95+
AppleID: &expectedAppleIDWithArgInput,
96+
APIKey: nil,
97+
},
98+
},
99+
{
100+
name: "Connection active (Apple ID), inputs (Apple ID) with ConnectionAppleIDSource",
101+
args: args{
102+
devportalConnection: &devportalservice.AppleDeveloperConnection{
103+
AppleIDConnection: &argAppleIDConnection,
104+
},
105+
authSources: []Source{&ConnectionAppleIDSource{}},
106+
inputs: argInput,
107+
},
108+
want: Credentials{
109+
AppleID: &expectedAppleIDWithArgConnection,
110+
APIKey: nil,
111+
},
112+
},
113+
{
114+
name: "Connection active (Apple ID), inputs (Apple ID) with InputAppleIDSource",
115+
args: args{
116+
devportalConnection: &devportalservice.AppleDeveloperConnection{
117+
AppleIDConnection: &argAppleIDConnection,
54118
},
119+
authSources: []Source{&InputAppleIDSource{}},
120+
inputs: argInput,
121+
},
122+
want: Credentials{
123+
AppleID: &expectedAppleIDWithArgInput,
124+
APIKey: nil,
125+
},
126+
},
127+
{
128+
name: "Connection active (Apple ID), inputs (Apple ID) with ConnectionAppleIDFastlaneSource",
129+
args: args{
130+
devportalConnection: &devportalservice.AppleDeveloperConnection{
131+
AppleIDConnection: &argAppleIDConnection,
132+
},
133+
authSources: []Source{&ConnectionAppleIDFastlaneSource{}},
134+
inputs: argInput,
135+
},
136+
want: Credentials{
137+
AppleID: &expectedAppleIDWithArgConnection,
138+
APIKey: nil,
139+
},
140+
},
141+
{
142+
name: "Connection active but missing password (Apple ID), inputs (Apple ID) with ConnectionAppleIDFastlaneSource",
143+
args: args{
144+
devportalConnection: &devportalservice.AppleDeveloperConnection{
145+
AppleIDConnection: &argAppleIDConnectionMissingPassword,
146+
},
147+
authSources: []Source{&ConnectionAppleIDFastlaneSource{}},
148+
inputs: argInput,
55149
},
56150
want: Credentials{
57151
AppleID: &AppleID{
58-
Username: "a", Password: "b", AppSpecificPassword: "c", Session: "",
152+
Username: argAppleIDConnection.AppleID,
153+
Password: argAppleIDConnection.Password,
154+
AppSpecificPassword: argInput.AppSpecificPassword,
155+
Session: "",
59156
},
60157
APIKey: nil,
61158
},
62159
},
160+
{
161+
name: "Connection active (Apple ID), inputs (Apple ID) with InputAppleIDFastlaneSource",
162+
args: args{
163+
devportalConnection: &devportalservice.AppleDeveloperConnection{
164+
AppleIDConnection: &argAppleIDConnection,
165+
},
166+
authSources: []Source{&InputAppleIDFastlaneSource{}},
167+
inputs: argInput,
168+
},
169+
want: Credentials{
170+
AppleID: &expectedAppleIDWithArgInput,
171+
APIKey: nil,
172+
},
173+
},
63174
{
64175
name: "Connection active (API Key), inputs (Apple ID)",
65176
args: args{
66177
devportalConnection: &devportalservice.AppleDeveloperConnection{
67-
APIKeyConnection: &devportalservice.APIKeyConnection{
68-
KeyID: "x", IssuerID: "y", PrivateKey: "z",
69-
},
178+
APIKeyConnection: &argAPIKeyConnection,
70179
},
71180
authSources: []Source{&ConnectionAPIKeySource{}, &ConnectionAppleIDSource{}, &InputAPIKeySource{}, &InputAppleIDSource{}},
72-
inputs: Inputs{
73-
Username: "a", Password: "b", AppSpecificPassword: "c",
74-
APIIssuer: "", APIKeyPath: "",
75-
},
181+
inputs: argInput,
76182
},
77183
want: Credentials{
78184
AppleID: nil,
79-
APIKey: &devportalservice.APIKeyConnection{
80-
KeyID: "x", IssuerID: "y", PrivateKey: "z",
81-
},
185+
APIKey: &expectedAppleIDWithAPIKeyConnection,
82186
},
83187
},
84188
{
85189
name: "Connection active (API Key), inputs (Apple ID), connection not enabled",
86190
args: args{
87191
devportalConnection: &devportalservice.AppleDeveloperConnection{
88-
APIKeyConnection: &devportalservice.APIKeyConnection{
89-
KeyID: "x", IssuerID: "y", PrivateKey: "z",
90-
},
192+
APIKeyConnection: &argAPIKeyConnection,
91193
},
92194
authSources: []Source{&InputAPIKeySource{}, &InputAppleIDSource{}},
93-
inputs: Inputs{
94-
Username: "a", Password: "b", AppSpecificPassword: "c",
95-
APIIssuer: "", APIKeyPath: "",
96-
},
195+
inputs: argInput,
97196
},
98197
want: Credentials{
99-
AppleID: &AppleID{
100-
Username: "a", Password: "b", AppSpecificPassword: "c", Session: "",
101-
},
102-
APIKey: nil,
198+
AppleID: &expectedAppleIDWithArgInput,
199+
APIKey: nil,
103200
},
104201
},
105202
}

appleauth/key_helper.go

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
package appleauth
22

33
import (
4-
"fmt"
54
"io/ioutil"
65
"net/http"
76
"net/url"
87
"path/filepath"
98
"regexp"
109

11-
"github.com/bitrise-io/go-utils/log"
10+
"github.com/bitrise-io/go-steputils/input"
11+
"github.com/bitrise-steplib/bitrise-step-export-universal-apk/filedownloader"
1212
)
1313

1414
func fetchPrivateKey(privateKeyURL string) ([]byte, string, error) {
@@ -17,46 +17,19 @@ func fetchPrivateKey(privateKeyURL string) ([]byte, string, error) {
1717
return nil, "", err
1818
}
1919

20-
key, err := copyOrDownloadFile(fileURL)
20+
// Download or load local file
21+
filedownloader := filedownloader.New(http.DefaultClient)
22+
fileProvider := input.NewFileProvider(filedownloader)
23+
localFile, err := fileProvider.LocalPath(fileURL.String())
2124
if err != nil {
2225
return nil, "", err
2326
}
24-
25-
return key, getKeyID(fileURL), nil
26-
}
27-
28-
func copyOrDownloadFile(u *url.URL) ([]byte, error) {
29-
// if file -> copy
30-
if u.Scheme == "file" {
31-
b, err := ioutil.ReadFile(u.Path)
32-
if err != nil {
33-
return nil, err
34-
}
35-
36-
return b, err
37-
}
38-
39-
// otherwise download
40-
resp, err := http.Get(u.String())
27+
key, err := ioutil.ReadFile(localFile)
4128
if err != nil {
42-
return nil, err
43-
}
44-
defer func() {
45-
if err := resp.Body.Close(); err != nil {
46-
log.Errorf("Failed to close file: %s", err)
47-
}
48-
}()
49-
50-
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
51-
return nil, fmt.Errorf("request failed with status %d", resp.StatusCode)
52-
}
53-
54-
contentBytes, err := ioutil.ReadAll(resp.Body)
55-
if err != nil {
56-
return nil, fmt.Errorf("failed to read response body: %s", err)
29+
return nil, "", err
5730
}
5831

59-
return contentBytes, nil
32+
return key, getKeyID(fileURL), nil
6033
}
6134

6235
func getKeyID(u *url.URL) string {

0 commit comments

Comments
 (0)