3737
3838import org .apache .cloudstack .acl .ControlledEntity ;
3939import org .apache .cloudstack .acl .InfrastructureEntity ;
40+ import org .apache .cloudstack .acl .SecurityChecker ;
4041import org .apache .cloudstack .acl .SecurityChecker .AccessType ;
4142import org .apache .cloudstack .api .ACL ;
43+ import org .apache .cloudstack .api .APICommand ;
4244import org .apache .cloudstack .api .ApiErrorCode ;
4345import org .apache .cloudstack .api .BaseAsyncCreateCmd ;
4446import org .apache .cloudstack .api .BaseCmd ;
5456import org .apache .cloudstack .api .command .user .event .ListEventsCmd ;
5557import org .apache .cloudstack .context .CallContext ;
5658
59+ import com .cloud .configuration .ConfigurationManager ;
60+ import com .cloud .dc .DataCenter ;
5761import com .cloud .exception .InvalidParameterValueException ;
62+ import com .cloud .exception .PermissionDeniedException ;
63+ import com .cloud .offering .DiskOffering ;
64+ import com .cloud .offering .ServiceOffering ;
5865import com .cloud .user .Account ;
5966import com .cloud .user .AccountManager ;
6067import com .cloud .utils .DateUtil ;
@@ -71,6 +78,17 @@ public class ParamProcessWorker implements DispatchWorker {
7178 @ Inject
7279 protected EntityManager _entityMgr ;
7380
81+ List <SecurityChecker > _secChecker ;
82+
83+ public List <SecurityChecker > getSecChecker () {
84+ return _secChecker ;
85+ }
86+
87+ @ Inject
88+ public void setSecChecker (List <SecurityChecker > secChecker ) {
89+ _secChecker = secChecker ;
90+ }
91+
7492 @ Override
7593 public void handle (final DispatchTask task ) {
7694 processParameters (task .getCmd (), task .getParams ());
@@ -214,27 +232,96 @@ public void processParameters(final BaseCmd cmd, final Map params) {
214232
215233
216234 private void doAccessChecks (final BaseCmd cmd , final Map <Object , AccessType > entitiesToAccess ) {
217- final Account caller = CallContext .current ().getCallingAccount ();
218- final Account owner = _accountMgr .getActiveAccountById (cmd .getEntityOwnerId ());
235+ Account caller = CallContext .current ().getCallingAccount ();
219236
220- if (cmd instanceof BaseAsyncCreateCmd ) {
221- //check that caller can access the owner account.
222- _accountMgr .checkAccess (caller , null , true , owner );
223- }
237+ APICommand commandAnnotation = cmd .getClass ().getAnnotation (APICommand .class );
238+ String apiName = commandAnnotation != null ? commandAnnotation .name () : null ;
224239
225240 if (!entitiesToAccess .isEmpty ()) {
226- //check that caller can access the owner account.
227- _accountMgr . checkAccess ( caller , null , true , owner );
228- for (final Object entity : entitiesToAccess .keySet ()) {
241+ List < ControlledEntity > entitiesToOperate = new ArrayList < ControlledEntity >();
242+
243+ for (Object entity : entitiesToAccess .keySet ()) {
229244 if (entity instanceof ControlledEntity ) {
230- _accountMgr .checkAccess (caller , entitiesToAccess .get (entity ), true , (ControlledEntity )entity );
245+
246+ if (AccessType .OperateEntry == entitiesToAccess .get (entity )) {
247+ entitiesToOperate .add ((ControlledEntity ) entity );
248+ } else {
249+ _accountMgr .checkAccess (caller , entitiesToAccess .get (entity ), false , apiName ,
250+ (ControlledEntity ) entity );
251+ }
231252 } else if (entity instanceof InfrastructureEntity ) {
232- //FIXME: Move this code in adapter, remove code from Account manager
253+ if (entity instanceof DataCenter ) {
254+ checkZoneAccess (caller , (DataCenter ) entity );
255+ } else if (entity instanceof ServiceOffering ) {
256+ checkServiceOfferingAccess (caller , (ServiceOffering ) entity );
257+ } else if (entity instanceof DiskOffering ) {
258+ checkDiskOfferingAccess (caller , (DiskOffering ) entity );
259+ }
233260 }
234261 }
262+
263+ if (!entitiesToOperate .isEmpty ()) {
264+ _accountMgr .checkAccess (caller , AccessType .OperateEntry , false , apiName ,
265+ (ControlledEntity []) entitiesToOperate .toArray ());
266+ }
267+
235268 }
236269 }
237270
271+ private void checkDiskOfferingAccess (Account caller , DiskOffering dof ) {
272+ for (SecurityChecker checker : _secChecker ) {
273+ if (checker .checkAccess (caller , dof )) {
274+ if (s_logger .isDebugEnabled ()) {
275+ s_logger .debug ("Access granted to " + caller + " to disk offering:" + dof .getId () + " by "
276+ + checker .getName ());
277+ }
278+ return ;
279+ } else {
280+ throw new PermissionDeniedException ("Access denied to " + caller + " by " + checker .getName ());
281+ }
282+ }
283+
284+ assert false : "How can all of the security checkers pass on checking this caller?" ;
285+ throw new PermissionDeniedException ("There's no way to confirm " + caller + " has access to disk offering:"
286+ + dof .getId ());
287+ }
288+
289+ private void checkServiceOfferingAccess (Account caller , ServiceOffering sof ) {
290+ for (SecurityChecker checker : _secChecker ) {
291+ if (checker .checkAccess (caller , sof )) {
292+ if (s_logger .isDebugEnabled ()) {
293+ s_logger .debug ("Access granted to " + caller + " to service offering:" + sof .getId () + " by "
294+ + checker .getName ());
295+ }
296+ return ;
297+ } else {
298+ throw new PermissionDeniedException ("Access denied to " + caller + " by " + checker .getName ());
299+ }
300+ }
301+
302+ assert false : "How can all of the security checkers pass on checking this caller?" ;
303+ throw new PermissionDeniedException ("There's no way to confirm " + caller + " has access to service offering:"
304+ + sof .getId ());
305+ }
306+
307+ private void checkZoneAccess (Account caller , DataCenter zone ) {
308+ for (SecurityChecker checker : _secChecker ) {
309+ if (checker .checkAccess (caller , zone )) {
310+ if (s_logger .isDebugEnabled ()) {
311+ s_logger .debug ("Access granted to " + caller + " to zone:" + zone .getId () + " by "
312+ + checker .getName ());
313+ }
314+ return ;
315+ } else {
316+ throw new PermissionDeniedException ("Access denied to " + caller + " by " + checker .getName ()
317+ + " for zone " + zone .getId ());
318+ }
319+ }
320+
321+ assert false : "How can all of the security checkers pass on checking this caller?" ;
322+ throw new PermissionDeniedException ("There's no way to confirm " + caller + " has access to zone:"
323+ + zone .getId ());
324+ }
238325
239326 @ SuppressWarnings ({"unchecked" , "rawtypes" })
240327 private void setFieldValue (final Field field , final BaseCmd cmdObj , final Object paramObj , final Parameter annotation ) throws IllegalArgumentException , ParseException {
0 commit comments