forked from spiffe/go-spiffe
/
trustdomain.go
122 lines (108 loc) · 3.25 KB
/
trustdomain.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
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package spiffeid
import (
"net/url"
"strings"
)
// TrustDomain represents the trust domain portion of a SPIFFE ID (e.g.
// example.org).
type TrustDomain struct {
name string
}
// TrustDomainFromString returns a new TrustDomain from a string. The string
// can either be a trust domain name (e.g. example.org), or a valid SPIFFE ID
// URI (e.g. spiffe://example.org), otherwise an error is returned.
// See https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE-ID.md#21-trust-domain.
func TrustDomainFromString(idOrName string) (TrustDomain, error) {
switch {
case idOrName == "":
return TrustDomain{}, errMissingTrustDomain
case strings.Contains(idOrName, ":/"):
// The ID looks like it has something like a scheme separator, let's
// try to parse as an ID. We use :/ instead of :// since the
// diagnostics are better for a bad input like spiffe:/trustdomain.
id, err := FromString(idOrName)
if err != nil {
return TrustDomain{}, err
}
return id.TrustDomain(), nil
default:
for i := 0; i < len(idOrName); i++ {
if !isValidTrustDomainChar(idOrName[i]) {
return TrustDomain{}, errBadTrustDomainChar
}
}
return TrustDomain{name: idOrName}, nil
}
}
// TrustDomainFromURI returns a new TrustDomain from a URI. The URI must be a
// valid SPIFFE ID (see FromURI) or an error is returned. The trust domain is
// extracted from the host field.
func TrustDomainFromURI(uri *url.URL) (TrustDomain, error) {
id, err := FromURI(uri)
if err != nil {
return TrustDomain{}, err
}
return id.TrustDomain(), nil
}
// String returns the trust domain as a string, e.g. example.org.
func (td TrustDomain) String() string {
return td.name
}
// ID returns the SPIFFE ID of the trust domain.
func (td TrustDomain) ID() ID {
if id, err := makeID(td, ""); err == nil {
return id
}
return ID{}
}
// IDString returns a string representation of the the SPIFFE ID of the trust
// domain, e.g. "spiffe://example.org".
func (td TrustDomain) IDString() string {
return td.ID().String()
}
// IsZero returns true if the trust domain is the zero value.
func (td TrustDomain) IsZero() bool {
return td.name == ""
}
// Compare returns an integer comparing the trust domain to another
// lexicographically. The result will be 0 if td==other, -1 if td < other, and
// +1 if td > other.
func (td TrustDomain) Compare(other TrustDomain) int {
return strings.Compare(td.name, other.name)
}
// MarshalText returns a text representation of the trust domain. If the trust
// domain is the zero value, nil is returned.
func (td TrustDomain) MarshalText() ([]byte, error) {
if td.IsZero() {
return nil, nil
}
return []byte(td.String()), nil
}
// UnmarshalText decodes a text representation of the trust domain. If the text
// is empty, the trust domain is set to the zero value.
func (td *TrustDomain) UnmarshalText(text []byte) error {
if len(text) == 0 {
*td = TrustDomain{}
return nil
}
unmarshaled, err := TrustDomainFromString(string(text))
if err != nil {
return err
}
*td = unmarshaled
return nil
}
func isValidTrustDomainChar(c uint8) bool {
switch {
case c >= 'a' && c <= 'z':
return true
case c >= '0' && c <= '9':
return true
case c == '-', c == '.', c == '_':
return true
case isBackcompatTrustDomainChar(c):
return true
default:
return false
}
}