From 0dd19c197b27dcb92bae619dd1b59bb32600bb49 Mon Sep 17 00:00:00 2001 From: Chiradeep Vittal Date: Wed, 3 Nov 2010 00:13:03 -0700 Subject: [PATCH] VPN users API -- WIP --- .../agent/api/routing/VpnUsersCfgCommand.java | 14 ++- .../xen/resource/CitrixResourceBase.java | 13 ++ .../cloud/api/commands/ListVpnUsersCmd.java | 112 ++++++++++++++++++ .../cloud/api/response/VpnUsersResponse.java | 82 +++++++++++++ .../router/DomainRouterManagerImpl.java | 2 +- .../com/cloud/server/ManagementServer.java | 4 + .../cloud/server/ManagementServerImpl.java | 73 ++++++++++++ 7 files changed, 296 insertions(+), 4 deletions(-) create mode 100644 server/src/com/cloud/api/commands/ListVpnUsersCmd.java create mode 100644 server/src/com/cloud/api/response/VpnUsersResponse.java diff --git a/core/src/com/cloud/agent/api/routing/VpnUsersCfgCommand.java b/core/src/com/cloud/agent/api/routing/VpnUsersCfgCommand.java index a47d58e99cb..9e640873883 100644 --- a/core/src/com/cloud/agent/api/routing/VpnUsersCfgCommand.java +++ b/core/src/com/cloud/agent/api/routing/VpnUsersCfgCommand.java @@ -61,14 +61,15 @@ public class VpnUsersCfgCommand extends RoutingCommand { //for Gson } } - + String vpnAppliancePrivateIpAddress; //router private ip address typically UsernamePassword [] userpwds; protected VpnUsersCfgCommand() { } - public VpnUsersCfgCommand(List addUsers, List removeUsers) { + public VpnUsersCfgCommand(String routerIp, List addUsers, List removeUsers) { + this.vpnAppliancePrivateIpAddress = routerIp; userpwds = new UsernamePassword[addUsers.size() + removeUsers.size()]; int i = 0; for (VpnUserVO vpnUser: removeUsers) { @@ -83,5 +84,12 @@ public class VpnUsersCfgCommand extends RoutingCommand { public boolean executeInSequence() { return true; } - + + public String getVpnAppliancePrivateIpAddress() { + return vpnAppliancePrivateIpAddress; + } + + public String getRouterPrivateIpAddress() { + return vpnAppliancePrivateIpAddress; + } } diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 0b9960e0875..da6ca7a6e00 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -133,6 +133,7 @@ import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand; import com.cloud.agent.api.routing.SavePasswordCommand; import com.cloud.agent.api.routing.SetFirewallRuleCommand; import com.cloud.agent.api.routing.VmDataCommand; +import com.cloud.agent.api.routing.VpnUsersCfgCommand; import com.cloud.agent.api.storage.CopyVolumeAnswer; import com.cloud.agent.api.storage.CopyVolumeCommand; import com.cloud.agent.api.storage.CreateAnswer; @@ -645,6 +646,8 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR return execute((Start2Command)cmd); } else if (cmd instanceof RemoteAccessVpnCfgCommand) { return execute((RemoteAccessVpnCfgCommand)cmd); + } else if (cmd instanceof VpnUsersCfgCommand) { + return execute((VpnUsersCfgCommand)cmd); } else { return Answer.createUnsupportedCommandAnswer(cmd); } @@ -1226,6 +1229,16 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } return new Answer(cmd); } + + protected synchronized Answer execute(final VpnUsersCfgCommand cmd) { + String args = cmd.getRouterPrivateIpAddress(); + + String result = callHostPlugin("vmops", "lt2p_vpn", "args", args); + if (result == null || result.isEmpty()) { + return new Answer(cmd, false, "Configure VPN failed"); + } + return new Answer(cmd); + } protected Answer execute(final VmDataCommand cmd) { String routerPrivateIpAddress = cmd.getRouterPrivateIpAddress(); diff --git a/server/src/com/cloud/api/commands/ListVpnUsersCmd.java b/server/src/com/cloud/api/commands/ListVpnUsersCmd.java new file mode 100644 index 00000000000..c2fadd8491e --- /dev/null +++ b/server/src/com/cloud/api/commands/ListVpnUsersCmd.java @@ -0,0 +1,112 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.api.commands; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiDBUtils; +import com.cloud.api.BaseListCmd; +import com.cloud.api.Implementation; +import com.cloud.api.Parameter; +import com.cloud.api.response.ListResponse; +import com.cloud.api.response.VpnUsersResponse; +import com.cloud.network.VpnUserVO; +import com.cloud.user.Account; + +@Implementation(method="searchForVpnUsers", description="Lists vpn users") +public class ListVpnUsersCmd extends BaseListCmd { + public static final Logger s_logger = Logger.getLogger (ListVpnUsersCmd.class.getName()); + + private static final String s_name = "listvpnusersresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name="account", type=CommandType.STRING, description="the account of the remote access vpn. Must be used with the domainId parameter.") + private String accountName; + + @Parameter(name="domainid", type=CommandType.LONG, description="the domain ID of the remote access vpn. If used with the account parameter, lists remote access vpns for the account in the specified domain.") + private Long domainId; + + @Parameter(name="id", type=CommandType.LONG, description="the ID of the vpn user") + private Long id; + + @Parameter(name="username", type=CommandType.STRING, description="the username of the vpn user.") + private String userName; + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getAccountName() { + return accountName; + } + + public Long getDomainId() { + return domainId; + } + + public Long getId() { + return id; + } + + public String getUsername() { + return userName; + } + + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getName() { + return s_name; + } + + @Override @SuppressWarnings("unchecked") + public ListResponse getResponse() { + List vpnUsers = (List)getResponseObject(); + + ListResponse response = new ListResponse(); + List vpnResponses = new ArrayList(); + for (VpnUserVO vpnUser : vpnUsers) { + VpnUsersResponse vpnResponse = new VpnUsersResponse(); + vpnResponse.setId(vpnUser.getId()); + vpnResponse.setUsername(vpnUser.getUserName()); + vpnResponse.setAccountName(vpnUser.getAccountName()); + + Account accountTemp = ApiDBUtils.findAccountById(vpnUser.getAccountId()); + if (accountTemp != null) { + vpnResponse.setDomainId(accountTemp.getDomainId()); + vpnResponse.setDomainName(ApiDBUtils.findDomainById(accountTemp.getDomainId()).getName()); + } + + vpnResponse.setResponseName("vpnuser"); + vpnResponses.add(vpnResponse); + } + + response.setResponses(vpnResponses); + response.setResponseName(getName()); + return response; + } +} diff --git a/server/src/com/cloud/api/response/VpnUsersResponse.java b/server/src/com/cloud/api/response/VpnUsersResponse.java new file mode 100644 index 00000000000..b87637a4b4a --- /dev/null +++ b/server/src/com/cloud/api/response/VpnUsersResponse.java @@ -0,0 +1,82 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.api.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class VpnUsersResponse extends BaseResponse { + @SerializedName("id") @Param(description="the vpn userID") + private Long id; + + @SerializedName("username") @Param(description="the username of the vpn user") + private String userName; + + @SerializedName("account") @Param(description="the account of the remote access vpn") + private String accountName; + + @SerializedName("domainid") @Param(description="the domain id of the account of the remote access vpn") + private long domainId; + + @SerializedName("domainname") @Param(description="the domain name of the account of the remote access vpn") + private String domainName; + + public String getAccountName() { + return accountName; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return userName; + } + + public void setUsername(String name) { + this.userName = name; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + + } + + public void setDomainId(long domainId) { + this.domainId = domainId; + + } + + public void setDomainName(String name) { + this.domainName = name; + } + + public long getDomainId() { + return domainId; + } + + public String getDomainName() { + return domainName; + } + + +} diff --git a/server/src/com/cloud/network/router/DomainRouterManagerImpl.java b/server/src/com/cloud/network/router/DomainRouterManagerImpl.java index 3d17e31e4cc..b32fbd84c6f 100644 --- a/server/src/com/cloud/network/router/DomainRouterManagerImpl.java +++ b/server/src/com/cloud/network/router/DomainRouterManagerImpl.java @@ -2277,7 +2277,7 @@ public class DomainRouterManagerImpl implements DomainRouterManager, VirtualMach return false; } try { - Answer answer = _agentMgr.send(router.getHostId(), new VpnUsersCfgCommand(addUsers, removeUsers)); + Answer answer = _agentMgr.send(router.getHostId(), new VpnUsersCfgCommand(router.getPrivateIpAddress(), addUsers, removeUsers)); if (answer != null && answer.getResult()) { return true; } else { diff --git a/server/src/com/cloud/server/ManagementServer.java b/server/src/com/cloud/server/ManagementServer.java index 2505eed0c62..19c2ed4ba49 100755 --- a/server/src/com/cloud/server/ManagementServer.java +++ b/server/src/com/cloud/server/ManagementServer.java @@ -71,6 +71,7 @@ import com.cloud.api.commands.ListVMGroupsCmd; import com.cloud.api.commands.ListVMsCmd; import com.cloud.api.commands.ListVlanIpRangesCmd; import com.cloud.api.commands.ListVolumesCmd; +import com.cloud.api.commands.ListVpnUsersCmd; import com.cloud.api.commands.ListZonesByCmd; import com.cloud.api.commands.LockAccountCmd; import com.cloud.api.commands.LockUserCmd; @@ -115,6 +116,7 @@ import com.cloud.network.FirewallRuleVO; import com.cloud.network.IPAddressVO; import com.cloud.network.LoadBalancerVO; import com.cloud.network.RemoteAccessVpnVO; +import com.cloud.network.VpnUserVO; import com.cloud.network.security.NetworkGroupVO; import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.DiskOfferingVO; @@ -1129,4 +1131,6 @@ public interface ManagementServer { String uploadCertificate(UploadCustomCertificateCmd cmd); public List searchForRemoteAccessVpns(ListRemoteAccessVpnsCmd cmd); + + public List searchForVpnUsers(ListVpnUsersCmd cmd); } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 32ea89ca79a..04df9d9418d 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -119,6 +119,7 @@ import com.cloud.api.commands.ListVMGroupsCmd; import com.cloud.api.commands.ListVMsCmd; import com.cloud.api.commands.ListVlanIpRangesCmd; import com.cloud.api.commands.ListVolumesCmd; +import com.cloud.api.commands.ListVpnUsersCmd; import com.cloud.api.commands.ListZonesByCmd; import com.cloud.api.commands.LockAccountCmd; import com.cloud.api.commands.LockUserCmd; @@ -204,11 +205,13 @@ import com.cloud.network.LoadBalancerVMMapVO; import com.cloud.network.LoadBalancerVO; import com.cloud.network.NetworkManager; import com.cloud.network.RemoteAccessVpnVO; +import com.cloud.network.VpnUserVO; import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.LoadBalancerDao; import com.cloud.network.dao.LoadBalancerVMMapDao; import com.cloud.network.dao.RemoteAccessVpnDao; +import com.cloud.network.dao.VpnUserDao; import com.cloud.network.security.NetworkGroupManager; import com.cloud.network.security.NetworkGroupVO; import com.cloud.network.security.dao.NetworkGroupDao; @@ -379,6 +382,7 @@ public class ManagementServerImpl implements ManagementServer { private final UploadDao _uploadDao; private final CertificateDao _certDao; private final RemoteAccessVpnDao _remoteAccessVpnDao; + private final VpnUserDao _vpnUsersDao; private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker")); private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker")); @@ -454,6 +458,7 @@ public class ManagementServerImpl implements ManagementServer { _uploadDao = locator.getDao(UploadDao.class); _certDao = locator.getDao(CertificateDao.class); _remoteAccessVpnDao = locator.getDao(RemoteAccessVpnDao.class); + _vpnUsersDao = locator.getDao(VpnUserDao.class); _configs = _configDao.getConfiguration(); _userStatsDao = locator.getDao(UserStatisticsDao.class); _vmInstanceDao = locator.getDao(VMInstanceDao.class); @@ -6166,4 +6171,72 @@ public class ManagementServerImpl implements ManagementServer { return _remoteAccessVpnDao.search(sc, searchFilter); } + + @Override + public List searchForVpnUsers(ListVpnUsersCmd cmd) { + Account account = UserContext.current().getAccount(); + String accountName = cmd.getAccountName(); + Long domainId = cmd.getDomainId(); + Long accountId = null; + String username = cmd.getUsername(); + + + if ((account == null) || isAdmin(account.getType())) { + // validate domainId before proceeding + if (domainId != null) { + if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) { + throw new PermissionDeniedException("Unable to list remote access vpn users for domain id " + domainId + ", permission denied."); + } + if (accountName != null) { + Account userAccount = _accountDao.findActiveAccount(accountName, domainId); + if (userAccount != null) { + accountId = userAccount.getId(); + } else { + throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId); + } + } + } else { + domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId()); + } + } else { + accountId = account.getId(); + } + + Filter searchFilter = new Filter(VpnUserVO.class, "username", true, cmd.getStartIndex(), cmd.getPageSizeVal()); + + Object id = cmd.getId(); + + + SearchBuilder sb = _vpnUsersDao.createSearchBuilder(); + sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); + sb.and("username", sb.entity().getUserName(), SearchCriteria.Op.EQ); + sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ); + + if ((accountId == null) && (domainId != null)) { + // if accountId isn't specified, we can do a domain match for the admin case + SearchBuilder 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 sc = sb.create(); + + if (id != null) { + sc.setParameters("id", id); + } + + if (username != null) { + sc.setParameters("username", username); + } + + + if (accountId != null) { + sc.setParameters("accountId", accountId); + } else if (domainId != null) { + DomainVO domain = _domainDao.findById(domainId); + sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%"); + } + + return _vpnUsersDao.search(sc, searchFilter); + } }