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 123 124 125 126 127
|
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
}
// Name returns the trust domain name as a string, e.g. example.org.
func (td TrustDomain) Name() string {
return td.name
}
// String returns the trust domain name 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
}
}
|