Skip to content

Commit e2d11ba

Browse files
authored
preprocess urls to avoid errors in parsing (#14)
* replace forward slashes in aws credentials fixes #11
1 parent 4631bb0 commit e2d11ba

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

method/method.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ type objectLocation struct {
228228
}
229229

230230
func newLocation(value, s3Hostname string) (objectLocation, error) {
231-
uri, err := url.Parse(value)
231+
uri, err := url.Parse(preProcessURL(value))
232232
if err != nil {
233233
return objectLocation{}, err
234234
}
@@ -266,6 +266,30 @@ func newLocation(value, s3Hostname string) (objectLocation, error) {
266266
}, nil
267267
}
268268

269+
// replace any forward slashes in access key and secret
270+
func preProcessURL(url string) string {
271+
idx := strings.Index(url, "@")
272+
if idx < 0 {
273+
return url
274+
}
275+
sub := url[0:idx] // drop everything after the @
276+
sub = sub[5:] // drop the s3://
277+
278+
key := ""
279+
secret := ""
280+
tkns := strings.Split(sub, ":")
281+
if len(tkns) == 2 {
282+
key = tkns[0]
283+
secret = tkns[1]
284+
}
285+
processedKey := strings.ReplaceAll(key, "/", "%2F")
286+
processedSecret := strings.ReplaceAll(secret, "/", "%2F")
287+
288+
p := strings.ReplaceAll(url, key, processedKey)
289+
p = strings.ReplaceAll(p, secret, processedSecret)
290+
return p
291+
}
292+
269293
// uriAcquire downloads and stores objects from S3 based on the contents
270294
// of the provided Message.
271295
func (m *Method) uriAcquire(msg *message.Message) {

method/method_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,53 @@ func TestSettingRegion(t *testing.T) {
101101
t.Errorf("method.region = %s; expected %s", method.region, expected)
102102
}
103103
}
104+
105+
type locTest struct {
106+
url string
107+
accessKey string
108+
accessKeySecret string
109+
}
110+
111+
var locTests = []locTest{
112+
{
113+
"s3://fake-access-key-id:fake-access-key-secret@s3.amazonaws.com/apt-repo-bucket/apt/generic/python-bernhard_0.2.3-1_all.deb",
114+
"fake-access-key-id",
115+
"fake-access-key-secret",
116+
},
117+
{
118+
"s3://fake-ac/cess-key-id:fake-ac/cess-key-secret@s3.amazonaws.com/apt-repo-bucket/apt/generic/python-bernhard_0.2.3-1_all.deb",
119+
"fake-ac/cess-key-id",
120+
"fake-ac/cess-key-secret", // secret contains a forward slash
121+
},
122+
{
123+
"s3://fake-ac%2Fcess-key-id:fake-ac%2Fcess-key-secret@s3.amazonaws.com/apt-repo-bucket/apt/generic/python-bernhard_0.2.3-1_all.deb",
124+
"fake-ac/cess-key-id", // access key contains a forward slash that was encoded as %2F in the original url
125+
"fake-ac/cess-key-secret", // secret contains a forward slash that was encoded as %2F in the original url
126+
},
127+
{
128+
"s3://fake-access-key-id:@s3.amazonaws.com/apt-repo-bucket/apt/generic/python-bernhard_0.2.3-1_all.deb",
129+
"fake-access-key-id",
130+
"", // secret is blank
131+
},
132+
{
133+
"s3://:fake-access-key-secret@s3.amazonaws.com/apt-repo-bucket/apt/generic/python-bernhard_0.2.3-1_all.deb",
134+
"", // access key is blank
135+
"fake-access-key-secret",
136+
},
137+
}
138+
139+
func TestCreateLocation(t *testing.T) {
140+
for _, lt := range locTests {
141+
l, err := newLocation(lt.url, "s3.amazonaws.com")
142+
if err != nil {
143+
t.Fatalf("unexpected error: %v", err)
144+
}
145+
if l.uri.User.Username() != lt.accessKey {
146+
t.Errorf("unexpected accessKey: got %s, want %s", l.uri.User.Username(), lt.accessKey)
147+
}
148+
pass, _ := l.uri.User.Password()
149+
if pass != lt.accessKeySecret {
150+
t.Errorf("unexpected accessKeySecret: got %s, want %s", pass, lt.accessKeySecret)
151+
}
152+
}
153+
}

0 commit comments

Comments
 (0)