/
access.go
69 lines (59 loc) · 2.03 KB
/
access.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package sharing
import (
"context"
"net/http"
"time"
"github.com/zeebo/errs"
"storj.io/common/base58"
"storj.io/edge/pkg/authclient"
"storj.io/edge/pkg/errdata"
"storj.io/edge/pkg/linksharing/sharing/internal/signed"
"storj.io/uplink"
)
// parseAccess guesses whether access is an access grant or Access Key ID. If
// latter, it contacts authservice to resolve it. If the resolved access grant
// isn't public, it will assume r is AWS Signature Version 4-signed if it
// contains a valid signature. signedAccessValidityTolerance is how much r's
// signature time can be skewed. clientIP is the IP of the client that
// originated the request and cannot be empty.
func parseAccess(
ctx context.Context,
r *http.Request,
access string,
signedAccessValidityTolerance time.Duration,
cfg *authclient.AuthClient,
clientIP string,
) (_ *uplink.Access, err error) {
defer mon.Task()(&ctx)(&err)
wrappedParse := func(access string) (*uplink.Access, error) {
parsed, err := uplink.ParseAccess(access)
if err != nil {
return nil, errdata.WithStatus(err, http.StatusBadRequest)
}
return parsed, nil
}
if isProductionAccessGrant(access) {
return wrappedParse(access)
}
// otherwise, assume an access key.
authResp, err := cfg.ResolveWithCache(ctx, access, clientIP)
if err != nil {
return nil, err
}
if !authResp.Public { // If credentials aren't public, assume signed request.
if err = signed.VerifySigningInfo(r, authResp.SecretKey, time.Now(), signedAccessValidityTolerance); err != nil {
if errs.Is(err, signed.ErrMissingAuthorizationHeader) {
return nil, errdata.WithStatus(errs.New("non-public Access Key ID"), http.StatusForbidden)
}
return nil, errdata.WithStatus(err, http.StatusForbidden)
}
}
return wrappedParse(authResp.AccessGrant)
}
func isProductionAccessGrant(s string) bool {
// production access grants are base58check encoded with version zero.
_, version, err := base58.CheckDecode(s)
return err == nil && version == 0
}