@Override @DB public boolean addInstanceToGroups(final Long userVmId, final List<Long> groups) { if (!isVmSecurityGroupEnabled(userVmId)) { s_logger.warn( "User vm " + userVmId + " is not security group enabled, can't add it to security group"); return false; } if (groups != null && !groups.isEmpty()) { final Transaction txn = Transaction.currentTxn(); txn.start(); UserVm userVm = _userVMDao.acquireInLockTable( userVmId); // ensures that duplicate entries are not created. List<SecurityGroupVO> sgs = new ArrayList<SecurityGroupVO>(); for (Long sgId : groups) { sgs.add(_securityGroupDao.findById(sgId)); } final Set<SecurityGroupVO> uniqueGroups = new TreeSet<SecurityGroupVO>(new SecurityGroupVOComparator()); uniqueGroups.addAll(sgs); if (userVm == null) { s_logger.warn("Failed to acquire lock on user vm id=" + userVmId); } try { for (SecurityGroupVO securityGroup : uniqueGroups) { // don't let the group be deleted from under us. SecurityGroupVO ngrpLock = _securityGroupDao.lockRow(securityGroup.getId(), false); if (ngrpLock == null) { s_logger.warn( "Failed to acquire lock on network group id=" + securityGroup.getId() + " name=" + securityGroup.getName()); txn.rollback(); return false; } if (_securityGroupVMMapDao.findByVmIdGroupId(userVmId, securityGroup.getId()) == null) { SecurityGroupVMMapVO groupVmMapVO = new SecurityGroupVMMapVO(securityGroup.getId(), userVmId); _securityGroupVMMapDao.persist(groupVmMapVO); } } txn.commit(); return true; } finally { if (userVm != null) { _userVMDao.releaseFromLockTable(userVmId); } } } return false; }
@Override public SecurityGroupVO createSecurityGroup( String name, String description, Long domainId, Long accountId, String accountName) { SecurityGroupVO group = _securityGroupDao.findByAccountAndName(accountId, name); if (group == null) { group = new SecurityGroupVO(name, description, domainId, accountId); group = _securityGroupDao.persist(group); s_logger.debug("Created security group " + group + " for account id=" + accountId); } else { s_logger.debug("Returning existing security group " + group + " for account id=" + accountId); } return group; }
@Override public String getSecurityGroupsNamesForVm(long vmId) { try { List<SecurityGroupVMMapVO> networkGroupsToVmMap = _securityGroupVMMapDao.listByInstanceId(vmId); int size = 0; int j = 0; StringBuilder networkGroupNames = new StringBuilder(); if (networkGroupsToVmMap != null) { size = networkGroupsToVmMap.size(); for (SecurityGroupVMMapVO nG : networkGroupsToVmMap) { // get the group id and look up for the group name SecurityGroupVO currentNetworkGroup = _securityGroupDao.findById(nG.getSecurityGroupId()); networkGroupNames.append(currentNetworkGroup.getName()); if (j < (size - 1)) { networkGroupNames.append(","); j++; } } } return networkGroupNames.toString(); } catch (Exception e) { s_logger.warn("Error trying to get network groups for a vm: " + e); return null; } }
@Override @DB public boolean revokeSecurityGroupIngress(RevokeSecurityGroupIngressCmd cmd) { // input validation Account caller = UserContext.current().getCaller(); Long id = cmd.getId(); IngressRuleVO rule = _ingressRuleDao.findById(id); if (rule == null) { s_logger.debug("Unable to find ingress rule with id " + id); throw new InvalidParameterValueException("Unable to find ingress rule with id " + id); } // Check permissions SecurityGroup securityGroup = _securityGroupDao.findById(rule.getSecurityGroupId()); _accountMgr.checkAccess(caller, null, securityGroup); SecurityGroupVO groupHandle = null; final Transaction txn = Transaction.currentTxn(); try { txn.start(); // acquire lock on parent group (preserving this logic) groupHandle = _securityGroupDao.acquireInLockTable(rule.getSecurityGroupId()); if (groupHandle == null) { s_logger.warn("Could not acquire lock on security group id: " + rule.getSecurityGroupId()); return false; } _ingressRuleDao.remove(id); s_logger.debug("revokeSecurityGroupIngress succeeded for ingress rule id: " + id); final ArrayList<Long> affectedVms = new ArrayList<Long>(); affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(groupHandle.getId())); scheduleRulesetUpdateToHosts(affectedVms, true, null); return true; } catch (Exception e) { s_logger.warn("Exception caught when deleting ingress rules ", e); throw new CloudRuntimeException("Exception caught when deleting ingress rules", e); } finally { if (groupHandle != null) { _securityGroupDao.releaseFromLockTable(groupHandle.getId()); } txn.commit(); } }
@DB @Override @ActionEvent( eventType = EventTypes.EVENT_SECURITY_GROUP_DELETE, eventDescription = "deleting security group") public boolean deleteSecurityGroup(DeleteSecurityGroupCmd cmd) throws ResourceInUseException { Long groupId = cmd.getId(); Account caller = UserContext.current().getCaller(); SecurityGroupVO group = _securityGroupDao.findById(groupId); if (group == null) { throw new InvalidParameterValueException( "Unable to find network group: " + groupId + "; failed to delete group."); } // check permissions _accountMgr.checkAccess(caller, null, group); final Transaction txn = Transaction.currentTxn(); txn.start(); group = _securityGroupDao.lockRow(groupId, true); if (group == null) { throw new InvalidParameterValueException("Unable to find security group by id " + groupId); } if (group.getName().equalsIgnoreCase(SecurityGroupManager.DEFAULT_GROUP_NAME)) { throw new InvalidParameterValueException("The network group default is reserved"); } List<IngressRuleVO> allowingRules = _ingressRuleDao.listByAllowedSecurityGroupId(groupId); List<SecurityGroupVMMapVO> securityGroupVmMap = _securityGroupVMMapDao.listBySecurityGroup(groupId); if (!allowingRules.isEmpty()) { throw new ResourceInUseException( "Cannot delete group when there are ingress rules that allow this group"); } else if (!securityGroupVmMap.isEmpty()) { throw new ResourceInUseException("Cannot delete group when it's in use by virtual machines"); } _securityGroupDao.expunge(groupId); txn.commit(); s_logger.debug("Deleted security group id=" + groupId); return true; }
@Override public List<SecurityGroupVO> getSecurityGroupsForVm(long vmId) { List<SecurityGroupVMMapVO> securityGroupsToVmMap = _securityGroupVMMapDao.listByInstanceId(vmId); List<SecurityGroupVO> secGrps = new ArrayList<SecurityGroupVO>(); if (securityGroupsToVmMap != null && securityGroupsToVmMap.size() > 0) { for (SecurityGroupVMMapVO sG : securityGroupsToVmMap) { SecurityGroupVO currSg = _securityGroupDao.findById(sG.getSecurityGroupId()); secGrps.add(currSg); } } return secGrps; }
@Override public SecurityGroupVO createDefaultSecurityGroup(Long accountId) { SecurityGroupVO groupVO = _securityGroupDao.findByAccountAndName(accountId, SecurityGroupManager.DEFAULT_GROUP_NAME); if (groupVO == null) { Account accVO = _accountDao.findById(accountId); if (accVO != null) { return createSecurityGroup( SecurityGroupManager.DEFAULT_GROUP_NAME, SecurityGroupManager.DEFAULT_GROUP_DESCRIPTION, accVO.getDomainId(), accVO.getId(), accVO.getAccountName()); } } return groupVO; }
private List<SecurityGroupRulesVO> listSecurityGroupRulesByVM(long vmId) { List<SecurityGroupRulesVO> results = new ArrayList<SecurityGroupRulesVO>(); List<SecurityGroupVMMapVO> networkGroupMappings = _securityGroupVMMapDao.listByInstanceId(vmId); if (networkGroupMappings != null) { for (SecurityGroupVMMapVO networkGroupMapping : networkGroupMappings) { SecurityGroupVO group = _securityGroupDao.findById(networkGroupMapping.getSecurityGroupId()); List<SecurityGroupRulesVO> rules = _securityGroupRulesDao.listSecurityGroupRules( group.getAccountId(), networkGroupMapping.getGroupName()); if (rules != null) { results.addAll(rules); } } } return results; }
@Override @ActionEvent( eventType = EventTypes.EVENT_SECURITY_GROUP_CREATE, eventDescription = "creating security group") public SecurityGroupVO createSecurityGroup(CreateSecurityGroupCmd cmd) throws PermissionDeniedException, InvalidParameterValueException { String name = cmd.getSecurityGroupName(); Account caller = UserContext.current().getCaller(); Account owner = _accountMgr.finalizeOwner(caller, cmd.getAccountName(), cmd.getDomainId()); if (_securityGroupDao.isNameInUse( owner.getId(), owner.getDomainId(), cmd.getSecurityGroupName())) { throw new InvalidParameterValueException( "Unable to create security group, a group with name " + name + " already exisits."); } return createSecurityGroup( cmd.getSecurityGroupName(), cmd.getDescription(), owner.getDomainId(), owner.getAccountId(), owner.getAccountName()); }
@Override @DB @SuppressWarnings("rawtypes") public List<IngressRuleVO> authorizeSecurityGroupIngress(AuthorizeSecurityGroupIngressCmd cmd) { Long securityGroupId = cmd.getSecurityGroupId(); String protocol = cmd.getProtocol(); Integer startPort = cmd.getStartPort(); Integer endPort = cmd.getEndPort(); Integer icmpType = cmd.getIcmpType(); Integer icmpCode = cmd.getIcmpCode(); List<String> cidrList = cmd.getCidrList(); Map groupList = cmd.getUserSecurityGroupList(); Integer startPortOrType = null; Integer endPortOrCode = null; // Validate parameters SecurityGroup securityGroup = _securityGroupDao.findById(securityGroupId); if (securityGroup == null) { throw new InvalidParameterValueException( "Unable to find security group by id " + securityGroupId); } if (cidrList == null && groupList == null) { throw new InvalidParameterValueException( "At least one cidr or at least one security group needs to be specified"); } Account caller = UserContext.current().getCaller(); Account owner = _accountMgr.getAccount(securityGroup.getAccountId()); if (owner == null) { throw new InvalidParameterValueException( "Unable to find security group owner by id=" + securityGroup.getAccountId()); } // Verify permissions _accountMgr.checkAccess(caller, null, securityGroup); Long domainId = owner.getDomainId(); if (protocol == null) { protocol = NetUtils.ALL_PROTO; } if (!NetUtils.isValidSecurityGroupProto(protocol)) { throw new InvalidParameterValueException("Invalid protocol " + protocol); } if ("icmp".equalsIgnoreCase(protocol)) { if ((icmpType == null) || (icmpCode == null)) { throw new InvalidParameterValueException( "Invalid ICMP type/code specified, icmpType = " + icmpType + ", icmpCode = " + icmpCode); } if (icmpType == -1 && icmpCode != -1) { throw new InvalidParameterValueException("Invalid icmp type range"); } if (icmpCode > 255) { throw new InvalidParameterValueException("Invalid icmp code "); } startPortOrType = icmpType; endPortOrCode = icmpCode; } else if (protocol.equals(NetUtils.ALL_PROTO)) { if ((startPort != null) || (endPort != null)) { throw new InvalidParameterValueException( "Cannot specify startPort or endPort without specifying protocol"); } startPortOrType = 0; endPortOrCode = 0; } else { if ((startPort == null) || (endPort == null)) { throw new InvalidParameterValueException( "Invalid port range specified, startPort = " + startPort + ", endPort = " + endPort); } if (startPort == 0 && endPort == 0) { endPort = 65535; } if (startPort > endPort) { throw new InvalidParameterValueException("Invalid port range " + startPort + ":" + endPort); } if (startPort > 65535 || endPort > 65535 || startPort < -1 || endPort < -1) { throw new InvalidParameterValueException( "Invalid port numbers " + startPort + ":" + endPort); } if (startPort < 0 || endPort < 0) { throw new InvalidParameterValueException("Invalid port range " + startPort + ":" + endPort); } startPortOrType = startPort; endPortOrCode = endPort; } protocol = protocol.toLowerCase(); List<SecurityGroupVO> authorizedGroups = new ArrayList<SecurityGroupVO>(); if (groupList != null) { Collection userGroupCollection = groupList.values(); Iterator iter = userGroupCollection.iterator(); while (iter.hasNext()) { HashMap userGroup = (HashMap) iter.next(); String group = (String) userGroup.get("group"); String authorizedAccountName = (String) userGroup.get("account"); if ((group == null) || (authorizedAccountName == null)) { throw new InvalidParameterValueException( "Invalid user group specified, fields 'group' and 'account' cannot be null, please specify groups in the form: userGroupList[0].group=XXX&userGroupList[0].account=YYY"); } Account authorizedAccount = _accountDao.findActiveAccount(authorizedAccountName, domainId); if (authorizedAccount == null) { throw new InvalidParameterValueException( "Nonexistent account: " + authorizedAccountName + " when trying to authorize ingress for " + securityGroupId + ":" + protocol + ":" + startPortOrType + ":" + endPortOrCode); } SecurityGroupVO groupVO = _securityGroupDao.findByAccountAndName(authorizedAccount.getId(), group); if (groupVO == null) { throw new InvalidParameterValueException( "Nonexistent group " + group + " for account " + authorizedAccountName + "/" + domainId + " is given, unable to authorize ingress."); } // Check permissions if (domainId != groupVO.getDomainId()) { throw new PermissionDeniedException( "Can't add security group id=" + groupVO.getDomainId() + " as it belongs to different domain"); } authorizedGroups.add(groupVO); } } final Transaction txn = Transaction.currentTxn(); final Set<SecurityGroupVO> authorizedGroups2 = new TreeSet<SecurityGroupVO>(new SecurityGroupVOComparator()); authorizedGroups2.addAll(authorizedGroups); // Ensure we don't re-lock the same row txn.start(); // Prevents other threads/management servers from creating duplicate ingress rules securityGroup = _securityGroupDao.acquireInLockTable(securityGroupId); if (securityGroup == null) { s_logger.warn("Could not acquire lock on network security group: id= " + securityGroupId); return null; } List<IngressRuleVO> newRules = new ArrayList<IngressRuleVO>(); try { for (final SecurityGroupVO ngVO : authorizedGroups2) { final Long ngId = ngVO.getId(); // Don't delete the referenced group from under us if (ngVO.getId() != securityGroup.getId()) { final SecurityGroupVO tmpGrp = _securityGroupDao.lockRow(ngId, false); if (tmpGrp == null) { s_logger.warn("Failed to acquire lock on security group: " + ngId); txn.rollback(); return null; } } IngressRuleVO ingressRule = _ingressRuleDao.findByProtoPortsAndAllowedGroupId( securityGroup.getId(), protocol, startPortOrType, endPortOrCode, ngVO.getId()); if (ingressRule != null) { continue; // rule already exists. } ingressRule = new IngressRuleVO( securityGroup.getId(), startPortOrType, endPortOrCode, protocol, ngVO.getId()); ingressRule = _ingressRuleDao.persist(ingressRule); newRules.add(ingressRule); } if (cidrList != null) { for (String cidr : cidrList) { IngressRuleVO ingressRule = _ingressRuleDao.findByProtoPortsAndCidr( securityGroup.getId(), protocol, startPortOrType, endPortOrCode, cidr); if (ingressRule != null) { continue; } ingressRule = new IngressRuleVO( securityGroup.getId(), startPortOrType, endPortOrCode, protocol, cidr); ingressRule = _ingressRuleDao.persist(ingressRule); newRules.add(ingressRule); } } if (s_logger.isDebugEnabled()) { s_logger.debug( "Added " + newRules.size() + " rules to security group " + securityGroup.getName()); } txn.commit(); final ArrayList<Long> affectedVms = new ArrayList<Long>(); affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(securityGroup.getId())); scheduleRulesetUpdateToHosts(affectedVms, true, null); return newRules; } catch (Exception e) { s_logger.warn("Exception caught when adding ingress rules ", e); throw new CloudRuntimeException("Exception caught when adding ingress rules", e); } finally { if (securityGroup != null) { _securityGroupDao.releaseFromLockTable(securityGroup.getId()); } } }
@Override public SecurityGroup getSecurityGroup(String name, long accountId) { return _securityGroupDao.findByAccountAndName(accountId, name); }
@Override public SecurityGroupVO getDefaultSecurityGroup(long accountId) { return _securityGroupDao.findByAccountAndName(accountId, DEFAULT_GROUP_NAME); }
@Override public List<SecurityGroupRulesVO> searchForSecurityGroupRules(ListSecurityGroupsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException { Account caller = UserContext.current().getCaller(); Long domainId = cmd.getDomainId(); String accountName = cmd.getAccountName(); Long instanceId = cmd.getVirtualMachineId(); String securityGroup = cmd.getSecurityGroupName(); Long id = cmd.getId(); Long accountId = null; if (instanceId != null) { UserVmVO userVM = _userVMDao.findById(instanceId); if (userVM == null) { throw new InvalidParameterValueException( "Unable to list network groups for virtual machine instance " + instanceId + "; instance not found."); } _accountMgr.checkAccess(caller, null, userVM); return listSecurityGroupRulesByVM(instanceId.longValue()); } if (_accountMgr.isAdmin(caller.getType())) { if (domainId != null) { Domain domain = _domainMgr.getDomain(domainId); if (domain == null) { throw new InvalidParameterValueException("Unable to find domain by id " + domainId); } _accountMgr.checkAccess(caller, domain); if (accountName != null) { Account account = _accountMgr.getActiveAccountByName(accountName, domainId); if (account == null) { throw new InvalidParameterValueException( "Unable to find account " + accountName + " in domain " + domainId); } _accountMgr.checkAccess(caller, null, account); accountId = account.getId(); } } } else { // regular user can see only his own security groups accountId = caller.getId(); } List<SecurityGroupRulesVO> securityRulesList = new ArrayList<SecurityGroupRulesVO>(); Filter searchFilter = new Filter(SecurityGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); Object keyword = cmd.getKeyword(); SearchBuilder<SecurityGroupVO> sb = _securityGroupDao.createSearchBuilder(); sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ); // only do a recursive domain search if the search is not limited by account or instance if ((accountId == null) && (instanceId == null) && (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)) { SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder(); domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); sb.join( "domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); } SearchCriteria<SecurityGroupVO> sc = sb.create(); if (id != null) { sc.setParameters("id", id); } if (securityGroup != null) { sc.setParameters("name", securityGroup); } if (accountId != null) { sc.setParameters("accountId", accountId); } // only do a recursive domain search if the search is not limited by account or instance if ((accountId == null) && (instanceId == null) && (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)) { DomainVO domain = _domainDao.findById(caller.getDomainId()); sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%"); } if (keyword != null) { SearchCriteria<SecurityGroupRulesVO> ssc = _securityGroupRulesDao.createSearchCriteria(); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%"); sc.addAnd("name", SearchCriteria.Op.SC, ssc); } List<SecurityGroupVO> securityGroups = _securityGroupDao.search(sc, searchFilter); for (SecurityGroupVO group : securityGroups) { securityRulesList.addAll(_securityGroupRulesDao.listSecurityRulesByGroupId(group.getId())); } return securityRulesList; }