forked from leg100/otf
/
subject.go
133 lines (110 loc) · 3.55 KB
/
subject.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
123
124
125
126
127
128
129
130
131
132
133
package agent
import (
"context"
"fmt"
"log/slog"
"github.com/tofutf/tofutf/internal"
"github.com/tofutf/tofutf/internal/rbac"
)
type (
// unregisteredServer is a server agent that is yet to register
unregisteredServerAgent struct {
internal.Subject
}
// unregisteredPoolAgent is a pool agent that is yet to register
unregisteredPoolAgent struct {
pool *Pool
agentTokenID string
internal.Subject
}
// serverAgent is a registered server agent (otfd) for the purposes of
// authorization and auditing.
serverAgent struct {
*Agent
}
// poolAgent is a registered pool agent (otf-agent) for the purposes of
// authorization and auditing.
poolAgent struct {
*unregisteredPoolAgent
agent *Agent
}
)
// registeredAgentFromContext retrieves a registered agent as subject
func registeredAgentFromContext(ctx context.Context) (internal.Subject, error) {
subj, err := internal.SubjectFromContext(ctx)
if err != nil {
return nil, err
}
switch subj.(type) {
case *poolAgent, *serverAgent:
return subj, nil
default:
return nil, fmt.Errorf("subject found in context but it is not a registered agent")
}
}
// poolAgentFromContext retrieves an pool agent subject from a context
func poolAgentFromContext(ctx context.Context) (*poolAgent, error) {
subj, err := internal.SubjectFromContext(ctx)
if err != nil {
return nil, err
}
agent, ok := subj.(*poolAgent)
if !ok {
return nil, fmt.Errorf("subject found in context but it is not a pool agent")
}
return agent, nil
}
func (a *poolAgent) LogValue() slog.Value {
attrs := append(
a.agent.LogValue().Group(),
slog.String("agent_token_id", a.agentTokenID),
)
return slog.GroupValue(attrs...)
}
func (a *poolAgent) String() string { return a.agent.ID }
func (a *poolAgent) IsSiteAdmin() bool { return true }
func (a *poolAgent) IsOwner(string) bool { return true }
func (a *poolAgent) Organizations() []string { return nil }
func (*poolAgent) CanAccessSite(action rbac.Action) bool {
return false
}
func (*poolAgent) CanAccessTeam(rbac.Action, string) bool {
return false
}
func (a *poolAgent) CanAccessOrganization(action rbac.Action, name string) bool {
return a.pool.Organization == name
}
func (a *poolAgent) CanAccessWorkspace(action rbac.Action, policy internal.WorkspacePolicy) bool {
return a.pool.Organization == policy.Organization
}
func (a *serverAgent) String() string { return a.ID }
func (a *serverAgent) IsSiteAdmin() bool { return true }
func (a *serverAgent) IsOwner(string) bool { return true }
func (a *serverAgent) Organizations() []string {
// an agent is not a member of organizations (although its agent pool is).
return nil
}
func (*serverAgent) CanAccessSite(action rbac.Action) bool {
// agent cannot carry out site-level actions
return false
}
func (*serverAgent) CanAccessTeam(rbac.Action, string) bool {
// agent cannot carry out team-level actions
return false
}
func (a *serverAgent) CanAccessOrganization(action rbac.Action, name string) bool {
// only a server-based agent can authenticate as an Agent, and if that is
// so, then it can carry out all organization-based actions.
//
// TODO: permit only those actions that an agent needs to carry out (get
// agent jobs, etc).
return a.IsServer()
}
func (a *serverAgent) CanAccessWorkspace(action rbac.Action, policy internal.WorkspacePolicy) bool {
// only a server-based agent can authenticate as an Agent, and if that is
// so, then it can carry out all workspace-based actions.
//
// TODO: permit only those actions that an agent needs to carry out (get
// agent jobs, etc).
return a.IsServer()
}