Skip to content

Commit 11ea13f

Browse files
author
abhishek
committed
Added the domain checker code and checks for a host of commands. This replaces the previous mechanism, and provides a way for us to validate the command executor as to whether he has access to the zone.
1 parent 3bcee34 commit 11ea13f

6 files changed

Lines changed: 131 additions & 30 deletions

File tree

api/src/com/cloud/acl/SecurityChecker.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44
package com.cloud.acl;
55

6+
import com.cloud.dc.DataCenter;
67
import com.cloud.domain.Domain;
78
import com.cloud.exception.PermissionDeniedException;
89
import com.cloud.user.Account;
@@ -53,6 +54,8 @@ public interface SecurityChecker extends Adapter {
5354
* @throws PermissionDeniedException if this adapter is suppose to authenticate ownership and the check failed.
5455
*/
5556
boolean checkAccess(User user, ControlledEntity entity) throws PermissionDeniedException;
57+
58+
boolean checkAccess(Account account, DataCenter zone) throws PermissionDeniedException;
5659

5760
// We should be able to use this method to check against commands. For example, we can
5861
// annotate the command with access annotations and this method can use it to extract

api/src/com/cloud/dc/DataCenter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ public interface DataCenter extends Grouping {
1313
String getDns1();
1414
String getDns2();
1515
String getGuestNetworkCidr();
16+
Long getDomainId();
1617
}

server/src/com/cloud/acl/DomainChecker.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
import javax.ejb.Local;
2121

2222
import com.cloud.api.BaseCmd;
23+
import com.cloud.dc.DataCenter;
2324
import com.cloud.domain.Domain;
25+
import com.cloud.domain.DomainVO;
2426
import com.cloud.domain.dao.DomainDao;
2527
import com.cloud.exception.PermissionDeniedException;
2628
import com.cloud.storage.LaunchPermissionVO;
@@ -97,4 +99,71 @@ public boolean checkAccess(User user, ControlledEntity entity) throws Permission
9799
Account account = _accountDao.findById(user.getAccountId());
98100
return checkAccess(account, entity);
99101
}
102+
103+
@Override
104+
public boolean checkAccess(Account account, DataCenter zone) throws PermissionDeniedException {
105+
if(account == null || zone.getDomainId() == null){//public zone
106+
return true;
107+
}else{
108+
//admin has all permissions
109+
if(account.getType() == Account.ACCOUNT_TYPE_ADMIN){
110+
return true;
111+
}
112+
//if account is normal user
113+
//check if account's domain is a child of zone's domain
114+
else if(account.getType() == Account.ACCOUNT_TYPE_NORMAL){
115+
if(account.getDomainId() == zone.getDomainId()){
116+
return true; //zone and account at exact node
117+
}else{
118+
DomainVO domainRecord = _domainDao.findById(account.getDomainId());
119+
if(domainRecord != null)
120+
{
121+
while(true){
122+
if(domainRecord.getId() == zone.getDomainId()){
123+
//found as a child
124+
return true;
125+
}
126+
if(domainRecord.getParent() != null)
127+
domainRecord = _domainDao.findById(domainRecord.getParent());
128+
else
129+
break;
130+
}
131+
}
132+
}
133+
//not found
134+
return false;
135+
}
136+
//if account is domain admin
137+
//check if the account's domain is either child of zone's domain, or if zone's domain is child of account's domain
138+
else if(account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN){
139+
if(account.getDomainId() == zone.getDomainId()){
140+
return true; //zone and account at exact node
141+
}else{
142+
DomainVO zoneDomainRecord = _domainDao.findById(zone.getDomainId());
143+
DomainVO accountDomainRecord = _domainDao.findById(account.getDomainId());
144+
if(accountDomainRecord != null)
145+
{
146+
DomainVO localRecord = accountDomainRecord;
147+
while(true){
148+
if(localRecord.getId() == zone.getDomainId()){
149+
//found as a child
150+
return true;
151+
}
152+
if(localRecord.getParent() != null)
153+
localRecord = _domainDao.findById(localRecord.getParent());
154+
else
155+
break;
156+
}
157+
}
158+
//didn't find in upper tree
159+
if(zoneDomainRecord.getPath().contains(accountDomainRecord.getPath())){
160+
return true;
161+
}
162+
}
163+
//not found
164+
return false;
165+
}
166+
}
167+
return false;
168+
}
100169
}

server/src/com/cloud/configuration/ConfigurationManager.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@
1919

2020
import java.util.List;
2121

22+
import com.cloud.dc.DataCenter;
2223
import com.cloud.dc.DataCenterVO;
2324
import com.cloud.dc.HostPodVO;
2425
import com.cloud.exception.ConcurrentOperationException;
2526
import com.cloud.exception.InsufficientAddressCapacityException;
27+
import com.cloud.exception.PermissionDeniedException;
2628
import com.cloud.service.ServiceOfferingVO;
2729
import com.cloud.storage.DiskOfferingVO;
30+
import com.cloud.user.Account;
2831
import com.cloud.utils.component.Manager;
2932

3033
/**
@@ -144,5 +147,8 @@ public interface ConfigurationManager extends Manager {
144147
* @return String containing a comma separated list of tags
145148
*/
146149
String listToCsvTags(List<String> tags);
150+
151+
void checkAccess(Account caller, DataCenter zone)
152+
throws PermissionDeniedException;
147153

148154
}

server/src/com/cloud/configuration/ConfigurationManagerImpl.java

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
import org.apache.log4j.Logger;
3131

32+
import com.cloud.acl.SecurityChecker;
3233
import com.cloud.api.BaseCmd;
3334
import com.cloud.api.ServerApiException;
3435
import com.cloud.api.commands.CreateCfgCmd;
@@ -56,8 +57,8 @@
5657
import com.cloud.dc.Pod;
5758
import com.cloud.dc.PodVlanMapVO;
5859
import com.cloud.dc.Vlan;
59-
import com.cloud.dc.Vlan.VlanType;
6060
import com.cloud.dc.VlanVO;
61+
import com.cloud.dc.Vlan.VlanType;
6162
import com.cloud.dc.dao.AccountVlanMapDao;
6263
import com.cloud.dc.dao.DataCenterDao;
6364
import com.cloud.dc.dao.DataCenterIpAddressDao;
@@ -80,8 +81,8 @@
8081
import com.cloud.network.dao.IPAddressDao;
8182
import com.cloud.offering.DiskOffering;
8283
import com.cloud.offering.NetworkOffering;
83-
import com.cloud.offering.NetworkOffering.GuestIpType;
8484
import com.cloud.offering.ServiceOffering;
85+
import com.cloud.offering.NetworkOffering.GuestIpType;
8586
import com.cloud.service.ServiceOfferingVO;
8687
import com.cloud.service.dao.ServiceOfferingDao;
8788
import com.cloud.storage.DiskOfferingVO;
@@ -95,6 +96,7 @@
9596
import com.cloud.user.dao.AccountDao;
9697
import com.cloud.user.dao.UserDao;
9798
import com.cloud.utils.NumbersUtil;
99+
import com.cloud.utils.component.Adapters;
98100
import com.cloud.utils.component.Inject;
99101
import com.cloud.utils.db.DB;
100102
import com.cloud.utils.db.Transaction;
@@ -136,6 +138,8 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
136138
@Inject SecondaryStorageVmDao _secStorageDao;
137139
@Inject AccountManager _accountMgr;
138140
@Inject NetworkManager _networkMgr;
141+
@Inject(adapter=SecurityChecker.class)
142+
Adapters<SecurityChecker> _secChecker;
139143

140144
private int _maxVolumeSizeInGb;
141145

@@ -1363,7 +1367,7 @@ public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws Insuffic
13631367
String vlanGateway = cmd.getGateway();
13641368
String vlanNetmask = cmd.getNetmask();
13651369

1366-
//check for hypervisor type to be xenserver
1370+
//check for hypervisor type to be xenserver
13671371
String hypervisorType = _configDao.getValue("hypervisor.type");
13681372

13691373
if(hypervisorType.equalsIgnoreCase("xenserver")) {
@@ -1393,11 +1397,13 @@ public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws Insuffic
13931397
throw new InvalidParameterValueException("Please specify a valid zone.");
13941398
}
13951399

1396-
//check if the account's domain is a child of the zone's domain, for adding vlan ip ranges
1397-
if(domainId != null && !_domainDao.isChildDomain(zone.getDomainId(), domainId)){
1398-
//this is for account specific case, as domainId != null
1399-
throw new PermissionDeniedException("The account associated with specific domain id:"+domainId+" doesn't have permissions to add vlan ip ranges for the zone:"+zone.getId());
1400-
}
1400+
// //check if the account's domain is a child of the zone's domain, for adding vlan ip ranges
1401+
// if(domainId != null && !_domainDao.isChildDomain(zone.getDomainId(), domainId)){
1402+
// //this is for account specific case, as domainId != null
1403+
// throw new PermissionDeniedException("The account associated with specific domain id:"+domainId+" doesn't have permissions to add vlan ip ranges for the zone:"+zone.getId());
1404+
// }
1405+
//ACL check
1406+
checkAccess(account, zone);
14011407

14021408
boolean associateIpRangeToAccount = false;
14031409
if (vlanType.equals(VlanType.VirtualNetwork)) {
@@ -2215,4 +2221,21 @@ public boolean deleteVlanIpRange(DeleteVlanIpRangeCmd cmd) throws InvalidParamet
22152221
return deleteVlanAndPublicIpRange(userId, vlanDbId);
22162222

22172223
}
2224+
2225+
@Override
2226+
public void checkAccess(Account caller, DataCenter zone) throws PermissionDeniedException {
2227+
for (SecurityChecker checker : _secChecker) {
2228+
if (checker.checkAccess(caller, zone)) {
2229+
if (s_logger.isDebugEnabled()) {
2230+
s_logger.debug("Access granted to " + caller + " to zone:" + zone.getId() + " by " + checker.getName());
2231+
}
2232+
return;
2233+
}else{
2234+
throw new PermissionDeniedException("Access denied to "+caller+" by "+checker.getName());
2235+
}
2236+
}
2237+
2238+
assert false : "How can all of the security checkers pass on checking this caller?";
2239+
throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to zone:" + zone.getId());
2240+
}
22182241
}

server/src/com/cloud/server/ManagementServerImpl.java

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
import org.apache.commons.codec.binary.Base64;
6161
import org.apache.log4j.Logger;
6262

63+
import com.cloud.acl.DomainChecker;
64+
import com.cloud.acl.SecurityChecker;
6365
import com.cloud.agent.AgentManager;
6466
import com.cloud.agent.api.Answer;
6567
import com.cloud.agent.api.GetVncPortAnswer;
@@ -150,6 +152,7 @@
150152
import com.cloud.consoleproxy.ConsoleProxyManager;
151153
import com.cloud.dc.AccountVlanMapVO;
152154
import com.cloud.dc.ClusterVO;
155+
import com.cloud.dc.DataCenter;
153156
import com.cloud.dc.DataCenterIpAddressVO;
154157
import com.cloud.dc.DataCenterVO;
155158
import com.cloud.dc.HostPodVO;
@@ -163,6 +166,7 @@
163166
import com.cloud.dc.dao.HostPodDao;
164167
import com.cloud.dc.dao.PodVlanMapDao;
165168
import com.cloud.dc.dao.VlanDao;
169+
import com.cloud.domain.Domain;
166170
import com.cloud.domain.DomainVO;
167171
import com.cloud.domain.dao.DomainDao;
168172
import com.cloud.event.EventState;
@@ -272,6 +276,7 @@
272276
import com.cloud.utils.PasswordGenerator;
273277
import com.cloud.utils.component.Adapters;
274278
import com.cloud.utils.component.ComponentLocator;
279+
import com.cloud.utils.component.Inject;
275280
import com.cloud.utils.concurrency.NamedThreadFactory;
276281
import com.cloud.utils.db.DB;
277282
import com.cloud.utils.db.Filter;
@@ -393,7 +398,7 @@ public class ManagementServerImpl implements ManagementServer {
393398
private boolean _networkGroupsEnabled = false;
394399

395400
private boolean _isHypervisorSnapshotCapable = false;
396-
401+
397402
protected ManagementServerImpl() {
398403
ComponentLocator locator = ComponentLocator.getLocator(Name);
399404
_lunDao = locator.getDao(PreallocatedLunDao.class);
@@ -461,7 +466,7 @@ protected ManagementServerImpl() {
461466
_snapMgr = locator.getManager(SnapshotManager.class);
462467
_networkGroupMgr = locator.getManager(NetworkGroupManager.class);
463468
_uploadMonitor = locator.getManager(UploadMonitor.class);
464-
469+
465470
_userAuthenticators = locator.getAdapters(UserAuthenticator.class);
466471
if (_userAuthenticators == null || !_userAuthenticators.isSet()) {
467472
s_logger.error("Unable to find an user authenticator.");
@@ -1116,7 +1121,8 @@ public UserVm deployVirtualMachine(DeployVMCmd cmd) throws ResourceAllocationExc
11161121
String[] networkGroups = null;
11171122
Long sizeObj = cmd.getSize();
11181123
long size = (sizeObj == null) ? 0 : sizeObj;
1119-
1124+
Account userAccount = null;
1125+
11201126
DataCenterVO dc = _dcDao.findById(dataCenterId);
11211127
if (dc == null) {
11221128
throw new InvalidParameterValueException("Unable to find zone: " + dataCenterId);
@@ -1128,7 +1134,7 @@ public UserVm deployVirtualMachine(DeployVMCmd cmd) throws ResourceAllocationExc
11281134
throw new PermissionDeniedException("Failed to deploy VM, invalid domain id (" + domainId + ") given.");
11291135
}
11301136
if (accountName != null) {
1131-
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
1137+
userAccount = _accountDao.findActiveAccount(accountName, domainId);
11321138
if (userAccount == null) {
11331139
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
11341140
}
@@ -1147,25 +1153,18 @@ public UserVm deployVirtualMachine(DeployVMCmd cmd) throws ResourceAllocationExc
11471153

11481154
if(domainId == null){
11491155
domainId = dc.getDomainId(); //get the domain id from zone
1150-
1151-
if(domainId == null){
1152-
//do nothing (public zone case)
1153-
}
1154-
else{
1155-
//check if this account has the permission to deploy a vm in this domain
1156-
if(ctxAccount != null){
1157-
if((ctxAccount.getType() == Account.ACCOUNT_TYPE_NORMAL) || ctxAccount.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN){
1158-
if(domainId == ctxAccount.getDomainId()){
1159-
//user in same domain as dedicated zone
1160-
}
1161-
else if ((!_domainDao.isChildDomain(domainId,ctxAccount.getDomainId()))){
1162-
//may need to revisit domain admin case for leaves
1163-
throw new PermissionDeniedException("Failed to deploy VM, user does not have permission to deploy a vm within this dedicated private zone under domain id:"+domainId);
1164-
}
1165-
}
1166-
}
1167-
}
11681156
}
1157+
1158+
if(domainId == null){
1159+
//do nothing (public zone case)
1160+
}
1161+
else{
1162+
if(userAccount != null){
1163+
_configMgr.checkAccess(userAccount, dc);//user deploying his own vm
1164+
}else{
1165+
_configMgr.checkAccess(ctxAccount, dc);
1166+
}
1167+
}
11691168

11701169
List<String> netGrpList = cmd.getNetworkGroupList();
11711170
if ((netGrpList != null) && !netGrpList.isEmpty()) {

0 commit comments

Comments
 (0)