1// Copyright (C) 2019 Storj Labs, Inc. 2// See LICENSE for copying information. 3 4package trust 5 6import ( 7 "context" 8 "regexp" 9 10 "github.com/zeebo/errs" 11) 12 13// Entry represents a trust entry. 14type Entry struct { 15 // SatelliteURL is the URL of the satellite 16 SatelliteURL SatelliteURL 17 18 // Authoritative indicates whether this entry came from an authoritative 19 // source. This impacts how URLS are aggregated. 20 Authoritative bool `json:"authoritative"` 21} 22 23// Source is a trust source for trusted Satellites. 24type Source interface { 25 // String is the string representation of the source. It is used as a key 26 // into the cache. 27 String() string 28 29 // Static returns true if the source is static. Static sources are not cached. 30 Static() bool 31 32 // FetchEntries returns the list of trust entries from the source. 33 FetchEntries(context.Context) ([]Entry, error) 34} 35 36// NewSource takes a configuration string returns a Source for that string. 37func NewSource(config string) (Source, error) { 38 schema, ok := isReserved(config) 39 if ok { 40 switch schema { 41 case "http", "https": 42 return NewHTTPSource(config) 43 case "storj": 44 return NewStaticURLSource(config) 45 default: 46 return nil, errs.New("unsupported schema %q", schema) 47 } 48 } 49 50 if isProbablySatelliteURL(config) { 51 return NewStaticURLSource(config) 52 } 53 54 return NewFileSource(config), nil 55} 56 57var reReserved = regexp.MustCompile(`^([a-zA-Z]{2,})://`) 58 59// isReserved returns the true if the string is within the reserved namespace 60// for trust sources, i.e. things that look like a URI scheme. Single letter 61// schemes are not in the reserved namespace since those collide with paths 62// starting with Windows drive letters. 63func isReserved(s string) (schema string, ok bool) { 64 m := reReserved.FindStringSubmatch(s) 65 if m == nil { 66 return "", false 67 } 68 return m[1], true 69} 70 71// reProbablySatelliteURL matches config strings that are (intended, but 72// possibly misconfigured) satellite URLs, like the following: 73// 74// - @ 75// - id@ 76// - host:9999 77// - id@host:9999 78var reProbablySatelliteURL = regexp.MustCompile(`@|(^[^/\\]{2,}:\d+$)`) 79 80func isProbablySatelliteURL(s string) bool { 81 // Painful esoteric paths to consider if you want to change the regex. None 82 // of the paths below should be parsed as satellite URLs, which the 83 // exception of the last one, which would fail since it does not contain an 84 // ID portion but would fail with good diagnostics. 85 // 1. http://basic:auth@example.com 86 // 2. c:/windows 87 // 3. c:\\windows 88 // 3. \\?\c:\\windows 89 // 4. probably other nightmarish windows paths 90 // 5. /posix/paths:are/terrible 91 // 6. posix.paths.are.really.terrible:7777 92 return reProbablySatelliteURL.MatchString(s) 93} 94