OLD | NEW |
1 // Copyright 2013 Canonical Ltd. | 1 // Copyright 2013 Canonical Ltd. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package apiserver | 4 package apiserver |
5 | 5 |
6 import ( | 6 import ( |
7 "launchpad.net/juju-core/state" | 7 "launchpad.net/juju-core/state" |
| 8 "launchpad.net/juju-core/state/apiserver/common" |
| 9 "launchpad.net/juju-core/state/apiserver/machiner" |
8 "launchpad.net/juju-core/state/multiwatcher" | 10 "launchpad.net/juju-core/state/multiwatcher" |
9 ) | 11 ) |
10 | 12 |
11 // srvRoot represents a single client's connection to the state. | 13 // srvRoot represents a single client's connection to the state. |
12 type srvRoot struct { | 14 type srvRoot struct { |
13 admin *srvAdmin | 15 admin *srvAdmin |
14 client *srvClient | 16 client *srvClient |
15 state *srvState | 17 state *srvState |
16 srv *Server | 18 srv *Server |
17 machiner *srvMachiner | |
18 resources *resources | 19 resources *resources |
19 | 20 |
20 user authUser | 21 user authUser |
21 } | 22 } |
22 | 23 |
23 func newStateServer(srv *Server) *srvRoot { | 24 func newStateServer(srv *Server) *srvRoot { |
24 r := &srvRoot{ | 25 r := &srvRoot{ |
25 srv: srv, | 26 srv: srv, |
26 resources: newResources(), | 27 resources: newResources(), |
27 } | 28 } |
28 r.admin = &srvAdmin{ | 29 r.admin = &srvAdmin{ |
29 root: r, | 30 root: r, |
30 } | 31 } |
31 r.client = &srvClient{ | 32 r.client = &srvClient{ |
32 root: r, | 33 root: r, |
33 } | 34 } |
34 r.state = &srvState{ | 35 r.state = &srvState{ |
35 root: r, | 36 root: r, |
36 } | 37 } |
37 r.machiner = &srvMachiner{ | |
38 st: r.srv.state, | |
39 auth: r, | |
40 } | |
41 return r | 38 return r |
42 } | 39 } |
43 | 40 |
44 // Kill implements rpc.Killer. It cleans up any resources that need | 41 // Kill implements rpc.Killer. It cleans up any resources that need |
45 // cleaning up to ensure that all outstanding requests return. | 42 // cleaning up to ensure that all outstanding requests return. |
46 func (r *srvRoot) Kill() { | 43 func (r *srvRoot) Kill() { |
47 r.resources.stopAll() | 44 r.resources.stopAll() |
48 } | 45 } |
49 | 46 |
50 // Admin returns an object that provides API access | 47 // Admin returns an object that provides API access |
51 // to methods that can be called even when not | 48 // to methods that can be called even when not |
52 // authenticated. | 49 // authenticated. |
53 func (r *srvRoot) Admin(id string) (*srvAdmin, error) { | 50 func (r *srvRoot) Admin(id string) (*srvAdmin, error) { |
54 if id != "" { | 51 if id != "" { |
55 // Safeguard id for possible future use. | 52 // Safeguard id for possible future use. |
56 » » return nil, errBadId | 53 » » return nil, common.ErrBadId |
57 } | 54 } |
58 return r.admin, nil | 55 return r.admin, nil |
59 } | 56 } |
60 | 57 |
61 // requireAgent checks whether the current client is an agent and hence | 58 // requireAgent checks whether the current client is an agent and hence |
62 // may access the agent APIs. We filter out non-agents when calling one | 59 // may access the agent APIs. We filter out non-agents when calling one |
63 // of the accessor functions (Machine, Unit, etc) which avoids us making | 60 // of the accessor functions (Machine, Unit, etc) which avoids us making |
64 // the check in every single request method. | 61 // the check in every single request method. |
65 func (r *srvRoot) requireAgent() error { | 62 func (r *srvRoot) requireAgent() error { |
66 e := r.user.authenticator() | 63 e := r.user.authenticator() |
67 if e == nil { | 64 if e == nil { |
68 » » return errNotLoggedIn | 65 » » return common.ErrNotLoggedIn |
69 } | 66 } |
70 if !isAgent(e) { | 67 if !isAgent(e) { |
71 » » return errPerm | 68 » » return common.ErrPerm |
72 } | 69 } |
73 return nil | 70 return nil |
74 } | 71 } |
75 | 72 |
76 // requireClient returns an error unless the current | 73 // requireClient returns an error unless the current |
77 // client is a juju client user. | 74 // client is a juju client user. |
78 func (r *srvRoot) requireClient() error { | 75 func (r *srvRoot) requireClient() error { |
79 e := r.user.authenticator() | 76 e := r.user.authenticator() |
80 if e == nil { | 77 if e == nil { |
81 » » return errNotLoggedIn | 78 » » return common.ErrNotLoggedIn |
82 } | 79 } |
83 if isAgent(e) { | 80 if isAgent(e) { |
84 » » return errPerm | 81 » » return common.ErrPerm |
85 } | 82 } |
86 return nil | 83 return nil |
87 } | 84 } |
88 | 85 |
89 // Machiner returns an object that provides access to the Machiner API | 86 // Machiner returns an object that provides access to the Machiner API |
90 // facade. Version argument is reserved for future use and currently | 87 // facade. The id argument is reserved for future use and currently |
91 // needs to be empty. | 88 // needs to be empty. |
92 func (r *srvRoot) Machiner(version string) (*srvMachiner, error) { | 89 func (r *srvRoot) Machiner(id string) (*machiner.Machiner, error) { |
93 » if err := r.requireAgent(); err != nil { | 90 » if id != "" { |
94 » » return nil, err | 91 » » // Safeguard id for possible future use. |
| 92 » » return nil, common.ErrBadId |
95 } | 93 } |
96 » if version != "" { | 94 » return machiner.New(r.srv.state, r) |
97 » » return nil, errBadVersion | |
98 » } | |
99 » return r.machiner, nil | |
100 } | 95 } |
101 | 96 |
102 // User returns an object that provides | 97 // User returns an object that provides |
103 // API access to methods on a state.User. | 98 // API access to methods on a state.User. |
104 func (r *srvRoot) User(name string) (*srvUser, error) { | 99 func (r *srvRoot) User(name string) (*srvUser, error) { |
105 // Any user is allowed to access their own user object. | 100 // Any user is allowed to access their own user object. |
106 // We check at this level rather than at the operation | 101 // We check at this level rather than at the operation |
107 // level to stop malicious probing for current user names. | 102 // level to stop malicious probing for current user names. |
108 // When we provide support for user administration, | 103 // When we provide support for user administration, |
109 // this will need to be changed to allow access to | 104 // this will need to be changed to allow access to |
110 // the administrator. | 105 // the administrator. |
111 e := r.user.authenticator() | 106 e := r.user.authenticator() |
112 if e == nil { | 107 if e == nil { |
113 » » return nil, errNotLoggedIn | 108 » » return nil, common.ErrNotLoggedIn |
114 } | 109 } |
115 if e.Tag() != name { | 110 if e.Tag() != name { |
116 » » return nil, errPerm | 111 » » return nil, common.ErrPerm |
117 } | 112 } |
118 u, err := r.srv.state.User(name) | 113 u, err := r.srv.state.User(name) |
119 if err != nil { | 114 if err != nil { |
120 return nil, err | 115 return nil, err |
121 } | 116 } |
122 return &srvUser{ | 117 return &srvUser{ |
123 root: r, | 118 root: r, |
124 u: u, | 119 u: u, |
125 }, nil | 120 }, nil |
126 } | 121 } |
127 | 122 |
128 // EntityWatcher returns an object that provides | 123 // EntityWatcher returns an object that provides |
129 // API access to methods on a state.EntityWatcher. | 124 // API access to methods on a state.EntityWatcher. |
130 // Each client has its own current set of watchers, stored | 125 // Each client has its own current set of watchers, stored |
131 // in r.resources. | 126 // in r.resources. |
132 func (r *srvRoot) EntityWatcher(id string) (srvEntityWatcher, error) { | 127 func (r *srvRoot) EntityWatcher(id string) (srvEntityWatcher, error) { |
133 if err := r.requireAgent(); err != nil { | 128 if err := r.requireAgent(); err != nil { |
134 return srvEntityWatcher{}, err | 129 return srvEntityWatcher{}, err |
135 } | 130 } |
136 watcher := r.resources.get(id) | 131 watcher := r.resources.get(id) |
137 if watcher == nil { | 132 if watcher == nil { |
138 » » return srvEntityWatcher{}, errUnknownWatcher | 133 » » return srvEntityWatcher{}, common.ErrUnknownWatcher |
139 } | 134 } |
140 if _, ok := watcher.resource.(*state.EntityWatcher); !ok { | 135 if _, ok := watcher.resource.(*state.EntityWatcher); !ok { |
141 » » return srvEntityWatcher{}, errUnknownWatcher | 136 » » return srvEntityWatcher{}, common.ErrUnknownWatcher |
142 } | 137 } |
143 return srvEntityWatcher{watcher}, nil | 138 return srvEntityWatcher{watcher}, nil |
144 } | 139 } |
145 | 140 |
146 // LifecycleWatcher returns an object that provides | 141 // LifecycleWatcher returns an object that provides |
147 // API access to methods on a state.LifecycleWatcher. | 142 // API access to methods on a state.LifecycleWatcher. |
148 // Each client has its own current set of watchers, stored | 143 // Each client has its own current set of watchers, stored |
149 // in r.resources. | 144 // in r.resources. |
150 func (r *srvRoot) LifecycleWatcher(id string) (srvLifecycleWatcher, error) { | 145 func (r *srvRoot) LifecycleWatcher(id string) (srvLifecycleWatcher, error) { |
151 if err := r.requireAgent(); err != nil { | 146 if err := r.requireAgent(); err != nil { |
152 return srvLifecycleWatcher{}, err | 147 return srvLifecycleWatcher{}, err |
153 } | 148 } |
154 watcher := r.resources.get(id) | 149 watcher := r.resources.get(id) |
155 if watcher == nil { | 150 if watcher == nil { |
156 » » return srvLifecycleWatcher{}, errUnknownWatcher | 151 » » return srvLifecycleWatcher{}, common.ErrUnknownWatcher |
157 } | 152 } |
158 if _, ok := watcher.resource.(*state.LifecycleWatcher); !ok { | 153 if _, ok := watcher.resource.(*state.LifecycleWatcher); !ok { |
159 » » return srvLifecycleWatcher{}, errUnknownWatcher | 154 » » return srvLifecycleWatcher{}, common.ErrUnknownWatcher |
160 } | 155 } |
161 return srvLifecycleWatcher{watcher}, nil | 156 return srvLifecycleWatcher{watcher}, nil |
162 } | 157 } |
163 | 158 |
164 // EnvironConfigWatcher returns an object that provides | 159 // EnvironConfigWatcher returns an object that provides |
165 // API access to methods on a state.EnvironConfigWatcher. | 160 // API access to methods on a state.EnvironConfigWatcher. |
166 // Each client has its own current set of watchers, stored | 161 // Each client has its own current set of watchers, stored |
167 // in r.resources. | 162 // in r.resources. |
168 func (r *srvRoot) EnvironConfigWatcher(id string) (srvEnvironConfigWatcher, erro
r) { | 163 func (r *srvRoot) EnvironConfigWatcher(id string) (srvEnvironConfigWatcher, erro
r) { |
169 if err := r.requireAgent(); err != nil { | 164 if err := r.requireAgent(); err != nil { |
170 return srvEnvironConfigWatcher{}, err | 165 return srvEnvironConfigWatcher{}, err |
171 } | 166 } |
172 watcher := r.resources.get(id) | 167 watcher := r.resources.get(id) |
173 if watcher == nil { | 168 if watcher == nil { |
174 » » return srvEnvironConfigWatcher{}, errUnknownWatcher | 169 » » return srvEnvironConfigWatcher{}, common.ErrUnknownWatcher |
175 } | 170 } |
176 if _, ok := watcher.resource.(*state.EnvironConfigWatcher); !ok { | 171 if _, ok := watcher.resource.(*state.EnvironConfigWatcher); !ok { |
177 » » return srvEnvironConfigWatcher{}, errUnknownWatcher | 172 » » return srvEnvironConfigWatcher{}, common.ErrUnknownWatcher |
178 } | 173 } |
179 return srvEnvironConfigWatcher{watcher}, nil | 174 return srvEnvironConfigWatcher{watcher}, nil |
180 } | 175 } |
181 | 176 |
182 // AllWatcher returns an object that provides API access to methods on | 177 // AllWatcher returns an object that provides API access to methods on |
183 // a state/multiwatcher.Watcher, which watches any changes to the | 178 // a state/multiwatcher.Watcher, which watches any changes to the |
184 // state. Each client has its own current set of watchers, stored in | 179 // state. Each client has its own current set of watchers, stored in |
185 // r.resources. | 180 // r.resources. |
186 func (r *srvRoot) AllWatcher(id string) (srvClientAllWatcher, error) { | 181 func (r *srvRoot) AllWatcher(id string) (srvClientAllWatcher, error) { |
187 if err := r.requireClient(); err != nil { | 182 if err := r.requireClient(); err != nil { |
188 return srvClientAllWatcher{}, err | 183 return srvClientAllWatcher{}, err |
189 } | 184 } |
190 watcher := r.resources.get(id) | 185 watcher := r.resources.get(id) |
191 if watcher == nil { | 186 if watcher == nil { |
192 » » return srvClientAllWatcher{}, errUnknownWatcher | 187 » » return srvClientAllWatcher{}, common.ErrUnknownWatcher |
193 } | 188 } |
194 if _, ok := watcher.resource.(*multiwatcher.Watcher); !ok { | 189 if _, ok := watcher.resource.(*multiwatcher.Watcher); !ok { |
195 » » return srvClientAllWatcher{}, errUnknownWatcher | 190 » » return srvClientAllWatcher{}, common.ErrUnknownWatcher |
196 } | 191 } |
197 return srvClientAllWatcher{watcher}, nil | 192 return srvClientAllWatcher{watcher}, nil |
198 | 193 |
199 } | 194 } |
200 | 195 |
201 // State returns an object that provides API access to top-level state methods. | 196 // State returns an object that provides API access to top-level state methods. |
202 func (r *srvRoot) State(id string) (*srvState, error) { | 197 func (r *srvRoot) State(id string) (*srvState, error) { |
203 if err := r.requireAgent(); err != nil { | 198 if err := r.requireAgent(); err != nil { |
204 return nil, err | 199 return nil, err |
205 } | 200 } |
206 if id != "" { | 201 if id != "" { |
207 // Safeguard id for possible future use. | 202 // Safeguard id for possible future use. |
208 » » return nil, errBadId | 203 » » return nil, common.ErrBadId |
209 } | 204 } |
210 return r.state, nil | 205 return r.state, nil |
211 } | 206 } |
212 | 207 |
213 // Client returns an object that provides access | 208 // Client returns an object that provides access |
214 // to methods accessible to non-agent clients. | 209 // to methods accessible to non-agent clients. |
215 func (r *srvRoot) Client(id string) (*srvClient, error) { | 210 func (r *srvRoot) Client(id string) (*srvClient, error) { |
216 if err := r.requireClient(); err != nil { | 211 if err := r.requireClient(); err != nil { |
217 return nil, err | 212 return nil, err |
218 } | 213 } |
219 if id != "" { | 214 if id != "" { |
220 // Safeguard id for possible future use. | 215 // Safeguard id for possible future use. |
221 » » return nil, errBadId | 216 » » return nil, common.ErrBadId |
222 } | 217 } |
223 return r.client, nil | 218 return r.client, nil |
224 } | 219 } |
225 | 220 |
226 type Tagger interface { | 221 // IsLoggedIn returns whether the user is currently logged in and |
227 » Tag() string | 222 // authenticated. |
| 223 func (r *srvRoot) IsLoggedIn() bool { |
| 224 » return r.user.authenticator() != nil |
228 } | 225 } |
229 | 226 |
230 // Authorizer interface defines per-method authorization calls. | 227 // AuthMachineAgent returns whether the current client is a machine agent. |
231 type Authorizer interface { | 228 func (r *srvRoot) AuthMachineAgent() bool { |
232 » AuthOwner(entity Tagger) bool | 229 » if !r.IsLoggedIn() { |
233 » AuthEnvironManager() bool | 230 » » return false |
| 231 » } |
| 232 » e := r.user.authenticator() |
| 233 » if _, ok := e.(*state.Machine); !ok { |
| 234 » » return false |
| 235 » } |
| 236 » return true |
234 } | 237 } |
235 | 238 |
236 // AuthOwner returns whether the authenticated user's tag matches the | 239 // AuthOwner returns whether the authenticated user's tag matches the |
237 // given entity's tag. | 240 // given entity's tag. |
238 func (r *srvRoot) AuthOwner(entity Tagger) bool { | 241 func (r *srvRoot) AuthOwner(entity common.Tagger) bool { |
239 authUser := r.user.authenticator() | 242 authUser := r.user.authenticator() |
240 return authUser.Tag() == entity.Tag() | 243 return authUser.Tag() == entity.Tag() |
241 } | 244 } |
242 | 245 |
243 // AuthEnvironManager returns whether the authenticated user is a | 246 // AuthEnvironManager returns whether the authenticated user is a |
244 // machine with running the ManageEnviron job. | 247 // machine with running the ManageEnviron job. |
245 func (r *srvRoot) AuthEnvironManager() bool { | 248 func (r *srvRoot) AuthEnvironManager() bool { |
246 authUser := r.user.authenticator() | 249 authUser := r.user.authenticator() |
247 return isMachineWithJob(authUser, state.JobManageEnviron) | 250 return isMachineWithJob(authUser, state.JobManageEnviron) |
248 } | 251 } |
OLD | NEW |