/** Get a list of security group ids for the slave */ private List<String> getEc2SecurityGroups(AmazonEC2 ec2) throws AmazonClientException { List<String> groupIds = new ArrayList<String>(); DescribeSecurityGroupsResult groupResult = getSecurityGroupsBy("group-name", securityGroupSet, ec2); if (groupResult.getSecurityGroups().size() == 0) { groupResult = getSecurityGroupsBy("group-id", securityGroupSet, ec2); } for (SecurityGroup group : groupResult.getSecurityGroups()) { if (group.getVpcId() != null && !group.getVpcId().isEmpty()) { List<Filter> filters = new ArrayList<Filter>(); filters.add(new Filter("vpc-id").withValues(group.getVpcId())); filters.add(new Filter("state").withValues("available")); filters.add(new Filter("subnet-id").withValues(getSubnetId())); DescribeSubnetsRequest subnetReq = new DescribeSubnetsRequest(); subnetReq.withFilters(filters); DescribeSubnetsResult subnetResult = ec2.describeSubnets(subnetReq); List<Subnet> subnets = subnetResult.getSubnets(); if (subnets != null && !subnets.isEmpty()) { groupIds.add(group.getGroupId()); } } } if (securityGroupSet.size() != groupIds.size()) { throw new AmazonClientException( "Security groups must all be VPC security groups to work in a VPC context"); } return groupIds; }
@Override public boolean isVmMappedToDefaultSecurityGroup(long vmId) { UserVmVO vm = _userVmMgr.getVirtualMachine(vmId); SecurityGroup defaultGroup = getDefaultSecurityGroup(vm.getAccountId()); if (defaultGroup == null) { s_logger.warn("Unable to find default security group for account id=" + vm.getAccountId()); return false; } SecurityGroupVMMapVO map = _securityGroupVMMapDao.findByVmIdGroupId(vmId, defaultGroup.getId()); if (map == null) { return false; } else { return true; } }
@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()); } } }