-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmds.go
More file actions
95 lines (82 loc) · 2.41 KB
/
Copy pathmds.go
File metadata and controls
95 lines (82 loc) · 2.41 KB
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package ctapkit
import (
"context"
"errors"
"net/http"
rtmds "github.com/go-ctap/kit/internal/mds"
"github.com/go-ctap/kit/model"
appmds "github.com/go-ctap/kit/model/mds"
"github.com/google/uuid"
)
// MDSOption configures a FIDO Metadata Service lookup.
type MDSOption func(*mdsConfig)
type mdsConfig struct {
source string
httpClient *http.Client
cacheDir string
refresh bool
}
// WithMDSSource overrides the default FIDO MDS3 blob URL.
func WithMDSSource(url string) MDSOption {
return func(config *mdsConfig) {
config.source = url
}
}
// WithMDSHTTPClient overrides the HTTP client used to fetch the MDS3 blob.
func WithMDSHTTPClient(client *http.Client) MDSOption {
return func(config *mdsConfig) {
config.httpClient = client
}
}
// WithMDSCacheDir overrides the directory used for the verified MDS blob cache.
func WithMDSCacheDir(path string) MDSOption {
return func(config *mdsConfig) {
config.cacheDir = path
}
}
// WithMDSRefresh bypasses the in-memory and filesystem MDS caches for one lookup.
func WithMDSRefresh() MDSOption {
return func(config *mdsConfig) {
config.refresh = true
}
}
// LookupMDS returns verified FIDO Metadata Service data for an AAGUID.
func LookupMDS(ctx context.Context, aaguid uuid.UUID, opts ...MDSOption) (appmds.LookupResult, error) {
return lookupMDS(ctx, aaguid, opts...)
}
func lookupMDS(
ctx context.Context,
aaguid uuid.UUID,
opts ...MDSOption,
) (appmds.LookupResult, error) {
var config mdsConfig
for _, opt := range opts {
if opt != nil {
opt(&config)
}
}
client := &rtmds.Client{
Source: config.source,
HTTPClient: config.httpClient,
CacheDir: config.cacheDir,
}
result, err := client.Lookup(ctx, aaguid, rtmds.LookupOptions{Refresh: config.refresh})
if err != nil {
return appmds.LookupResult{}, runtimeMDSError(err)
}
return result, nil
}
func runtimeMDSError(err error) error {
switch {
case errors.Is(err, rtmds.ErrInvalidAAGUID):
return model.NewRuntimeError(model.ErrorInvalidOperation, err.Error(), err)
case errors.Is(err, context.Canceled), errors.Is(err, context.DeadlineExceeded):
return model.NewRuntimeError(model.ErrorCanceled, "MDS lookup canceled", err)
case errors.Is(err, rtmds.ErrFetch):
return model.NewRuntimeError(model.ErrorTransportFailure, err.Error(), err)
case errors.Is(err, rtmds.ErrVerify):
return model.NewRuntimeError(model.ErrorInvalidState, err.Error(), err)
default:
return err
}
}