-
Notifications
You must be signed in to change notification settings - Fork 3
/
caveats.go
119 lines (98 loc) · 4.06 KB
/
caveats.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
package macaroon
import (
"encoding/json"
"fmt"
"time"
msgpack "github.com/vmihailenco/msgpack/v5"
)
// Caveat3P is a requirement that the token be presented along with a 3P discharge token.
type Caveat3P struct {
Location string
VerifierKey []byte // used by the initial issuer to verify discharge macaroon
Ticket []byte // used by the 3p service to construct discharge macaroon
// HMAC key for 3P caveat
rn []byte `msgpack:"-"`
}
func init() { RegisterCaveatType(&Caveat3P{}) }
func (c *Caveat3P) CaveatType() CaveatType { return Cav3P }
func (c *Caveat3P) Name() string { return "3P" }
func (c *Caveat3P) Prohibits(f Access) error {
// Caveat3P are part of token verification and have no role in
// access validation.
return fmt.Errorf("%w (3rd party caveat)", ErrBadCaveat)
}
// ValidityWindow establishes the window of time the token is valid for.
type ValidityWindow struct {
NotBefore int64 `json:"not_before"`
NotAfter int64 `json:"not_after"`
}
func init() { RegisterCaveatType(&ValidityWindow{}) }
func (c *ValidityWindow) CaveatType() CaveatType { return CavValidityWindow }
func (c *ValidityWindow) Name() string { return "ValidityWindow" }
func (c *ValidityWindow) Prohibits(f Access) error {
na := time.Unix(c.NotAfter, 0)
if f.Now().After(na) {
return fmt.Errorf("%w: token only valid until %s", ErrUnauthorized, na)
}
nb := time.Unix(c.NotBefore, 0)
if f.Now().Before(nb) {
return fmt.Errorf("%w: token not valid until %s", ErrUnauthorized, nb)
}
return nil
}
// BindToParentToken is used by discharge tokens to state that they may only
// be used to discharge 3P caveats for a specific root token or further
// attenuated versions of that token. This prevents a discharge token from
// being used with less attenuated versions of the specified token, effectively
// binding the discharge token to the root token. This caveat may appear
// multiple times to iteratively clamp down which versions of the root token
// the discharge token may be used with.
//
// The parent token is identified by a prefix of the SHA256 digest of the
// token's signature.
type BindToParentToken []byte
func init() { RegisterCaveatType(&BindToParentToken{}) }
func (c *BindToParentToken) CaveatType() CaveatType { return CavBindToParentToken }
func (c *BindToParentToken) Name() string { return "BindToParentToken" }
func (c *BindToParentToken) Prohibits(f Access) error {
// BindToParentToken are part of token verification and have no role in
// access validation.
return fmt.Errorf("%w (bind-to-parent)", ErrBadCaveat)
}
type UnregisteredCaveat struct {
Type CaveatType
Body any
RawJSON []byte
RawMsgpack []byte
}
func (c *UnregisteredCaveat) CaveatType() CaveatType { return c.Type }
func (c *UnregisteredCaveat) Name() string { return "Unregistered" }
func (c *UnregisteredCaveat) Prohibits(f Access) error {
return fmt.Errorf("%w (unregistered)", ErrBadCaveat)
}
func (c UnregisteredCaveat) MarshalMsgpack() ([]byte, error) {
// JSON is just for user-readability, but msgpack is what's used for
// signature verification. With struct tags, etc, it's lossy to encode
// things from json<->msgpack, so we just don't allow it.
if len(c.RawMsgpack) == 0 {
return nil, fmt.Errorf("cannot convert unregistered caveats from JSON to msgpack")
}
return c.RawMsgpack, nil
}
func (c *UnregisteredCaveat) UnmarshalMsgpack(data []byte) error {
c.RawMsgpack = data
return msgpack.Unmarshal(data, &c.Body)
}
func (c UnregisteredCaveat) MarshalJSON() ([]byte, error) {
// JSON is just for user-readability, but msgpack is what's used for
// signature verification. With struct tags, etc, it's lossy to encode
// things from json<->msgpack, so we just don't allow it.
if len(c.RawJSON) == 0 {
return nil, fmt.Errorf("cannot convert unregistered caveats from msgpack to JSON")
}
return c.RawJSON, nil
}
func (c *UnregisteredCaveat) UnmarshalJSON(data []byte) error {
c.RawJSON = data
return json.Unmarshal(data, &c.Body)
}