Skip to content

Commit 0df50ce

Browse files
committed
fix list dnsservers api, ui screens for dns servers, generate events
1 parent 369bb16 commit 0df50ce

File tree

13 files changed

+400
-102
lines changed

13 files changed

+400
-102
lines changed

api/src/main/java/com/cloud/event/EventTypes.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,8 +864,10 @@ public class EventTypes {
864864

865865
// DNS Framework Events
866866
public static final String EVENT_DNS_SERVER_ADD = "DNS.SERVER.ADD";
867+
public static final String EVENT_DNS_SERVER_UPDATE = "DNS.SERVER.UPDATE";
867868
public static final String EVENT_DNS_SERVER_DELETE = "DNS.SERVER.DELETE";
868869
public static final String EVENT_DNS_ZONE_CREATE = "DNS.ZONE.CREATE";
870+
public static final String EVENT_DNS_ZONE_UPDATE = "DNS.ZONE.UPDATE";
869871
public static final String EVENT_DNS_ZONE_DELETE = "DNS.ZONE.DELETE";
870872
public static final String EVENT_DNS_RECORD_CREATE = "DNS.RECORD.CREATE";
871873
public static final String EVENT_DNS_RECORD_DELETE = "DNS.RECORD.DELETE";

api/src/main/java/com/cloud/user/AccountService.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@
1919
import java.util.List;
2020
import java.util.Map;
2121

22-
import com.cloud.utils.Pair;
2322
import org.apache.cloudstack.acl.ControlledEntity;
2423
import org.apache.cloudstack.acl.RoleType;
2524
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
2625
import org.apache.cloudstack.api.command.admin.account.CreateAccountCmd;
2726
import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd;
2827
import org.apache.cloudstack.api.command.admin.user.RegisterUserKeyCmd;
2928
import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
29+
import org.apache.cloudstack.auth.UserTwoFactorAuthenticator;
30+
import org.apache.cloudstack.backup.BackupOffering;
31+
import org.apache.cloudstack.dns.DnsServer;
3032

3133
import com.cloud.dc.DataCenter;
3234
import com.cloud.domain.Domain;
@@ -35,8 +37,7 @@
3537
import com.cloud.offering.DiskOffering;
3638
import com.cloud.offering.NetworkOffering;
3739
import com.cloud.offering.ServiceOffering;
38-
import org.apache.cloudstack.auth.UserTwoFactorAuthenticator;
39-
import org.apache.cloudstack.backup.BackupOffering;
40+
import com.cloud.utils.Pair;
4041

4142
public interface AccountService {
4243

@@ -119,6 +120,8 @@ User createUser(String userName, String password, String firstName, String lastN
119120

120121
void checkAccess(Account account, BackupOffering bof) throws PermissionDeniedException;
121122

123+
void checkAccess(Account account, DnsServer dnsServer) throws PermissionDeniedException;
124+
122125
void checkAccess(User user, ControlledEntity entity);
123126

124127
void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName, ControlledEntity... entities) throws PermissionDeniedException;

api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ public class AddDnsServerCmd extends BaseCmd {
5555
@Parameter(name = ApiConstants.URL, type = CommandType.STRING, required = true, description = "API URL of the provider")
5656
private String url;
5757

58-
@Parameter(name = ApiConstants.PROVIDER_TYPE, type = CommandType.STRING, required = true, description = "Provider type (e.g., PowerDNS)")
59-
private String providerType;
58+
@Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, required = true, description = "Provider type (e.g., PowerDNS)")
59+
private String provider;
6060

6161
@Parameter(name = ApiConstants.DNS_USER_NAME, type = CommandType.STRING,
6262
description = "Username or email associated with the external DNS provider account (used for authentication)")
@@ -109,8 +109,8 @@ public List<String> getNameServers() {
109109
return nameServers;
110110
}
111111

112-
public DnsProviderType getProviderType() {
113-
DnsProviderType dnsProviderType = EnumUtils.getEnumIgnoreCase(DnsProviderType.class, providerType, DnsProviderType.PowerDNS);
112+
public DnsProviderType getProvider() {
113+
DnsProviderType dnsProviderType = EnumUtils.getEnumIgnoreCase(DnsProviderType.class, provider, DnsProviderType.PowerDNS);
114114
if (dnsProviderType == null) {
115115
throw new InvalidParameterValueException(String.format("Invalid value passed for provider type, valid values are: %s",
116116
EnumUtils.listValues(DnsProviderType.values())));

api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import org.apache.cloudstack.api.response.ListResponse;
3939

4040
import com.cloud.network.Network;
41-
import com.cloud.user.Account;
4241
import com.cloud.utils.component.Manager;
4342
import com.cloud.utils.component.PluggableService;
4443
import com.cloud.vm.Nic;
@@ -75,7 +74,5 @@ public interface DnsProviderManager extends Manager, PluggableService {
7574

7675
boolean disassociateZoneFromNetwork(DisassociateDnsZoneFromNetworkCmd cmd);
7776

78-
void checkDnsServerPermissions(Account caller, DnsServer server);
79-
8077
String processDnsRecordForInstance(VirtualMachine instance, Network network, Nic nic, boolean isAdd);
8178
}

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
import org.apache.cloudstack.backup.BackupOffering;
3131
import org.apache.cloudstack.backup.dao.BackupOfferingDetailsDao;
3232
import org.apache.cloudstack.context.CallContext;
33-
import org.apache.cloudstack.dns.DnsProviderManager;
34-
import org.apache.cloudstack.dns.DnsServer;
3533
import org.apache.cloudstack.query.QueryService;
3634
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
3735
import org.springframework.stereotype.Component;
@@ -103,8 +101,6 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
103101
private ProjectDao projectDao;
104102
@Inject
105103
private AccountService accountService;
106-
@Inject
107-
private DnsProviderManager dnsProviderManager;
108104

109105
protected DomainChecker() {
110106
super();
@@ -220,8 +216,6 @@ public boolean checkAccess(Account caller, ControlledEntity entity, AccessType a
220216
_networkMgr.checkRouterPermissions(caller, (VirtualRouter)entity);
221217
} else if (entity instanceof AffinityGroup) {
222218
return false;
223-
} else if (entity instanceof DnsServer) {
224-
dnsProviderManager.checkDnsServerPermissions(caller, (DnsServer) entity);
225219
} else {
226220
validateCallerHasAccessToEntityOwner(caller, entity, accessType);
227221
}

server/src/main/java/com/cloud/user/AccountManagerImpl.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,9 @@
179179
import com.cloud.utils.ConstantTimeComparator;
180180
import com.cloud.utils.NumbersUtil;
181181
import com.cloud.utils.Pair;
182+
import com.cloud.utils.StringUtils;
182183
import com.cloud.utils.Ternary;
183184
import com.cloud.utils.UuidUtils;
184-
import com.cloud.utils.StringUtils;
185185
import com.cloud.utils.component.ComponentContext;
186186
import com.cloud.utils.component.Manager;
187187
import com.cloud.utils.component.ManagerBase;
@@ -737,8 +737,7 @@ public void checkAccess(Account caller, AccessType accessType, boolean sameOwner
737737
}
738738
if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate)
739739
&& !(entity instanceof Network && (accessType == AccessType.UseEntry || accessType == AccessType.OperateEntry))
740-
&& !(entity instanceof AffinityGroup) && !(entity instanceof VirtualRouter)
741-
&& !(entity instanceof DnsServer)) {
740+
&& !(entity instanceof AffinityGroup) && !(entity instanceof VirtualRouter)) {
742741
List<ControlledEntity> toBeChecked = domains.get(entity.getDomainId());
743742
// for templates, we don't have to do cross domains check
744743
if (toBeChecked == null) {
@@ -3636,6 +3635,20 @@ public void checkAccess(Account account, BackupOffering bof) throws PermissionDe
36363635
throw new PermissionDeniedException("There's no way to confirm " + account + " has access to " + bof);
36373636
}
36383637

3638+
@Override
3639+
public void checkAccess(Account caller, DnsServer dnsServer) throws PermissionDeniedException {
3640+
if (caller.getId() == dnsServer.getAccountId()) {
3641+
return;
3642+
}
3643+
if (!dnsServer.isPublicServer()) {
3644+
throw new PermissionDeniedException(caller + "is not allowed to access the DNS server " + dnsServer.getName());
3645+
}
3646+
Account owner = getAccount(dnsServer.getAccountId());
3647+
if (!_domainDao.isChildDomain(owner.getDomainId(), caller.getDomainId())) {
3648+
throw new PermissionDeniedException(caller + "is not allowed to access the DNS server " + dnsServer.getName());
3649+
}
3650+
}
3651+
36393652
@Override
36403653
public void checkAccess(User user, ControlledEntity entity) throws PermissionDeniedException {
36413654
for (SecurityChecker checker : _securityCheckers) {

server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java

Lines changed: 25 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,20 @@
6060
import org.springframework.stereotype.Component;
6161

6262
import com.cloud.domain.dao.DomainDao;
63+
import com.cloud.event.ActionEvent;
64+
import com.cloud.event.EventTypes;
6365
import com.cloud.exception.InvalidParameterValueException;
6466
import com.cloud.exception.PermissionDeniedException;
6567
import com.cloud.network.Network;
6668
import com.cloud.network.dao.NetworkDao;
6769
import com.cloud.network.dao.NetworkVO;
68-
import com.cloud.projects.Project;
6970
import com.cloud.user.Account;
7071
import com.cloud.user.AccountManager;
7172
import com.cloud.utils.Pair;
7273
import com.cloud.utils.StringUtils;
73-
import com.cloud.utils.Ternary;
7474
import com.cloud.utils.component.ManagerBase;
7575
import com.cloud.utils.component.PluggableService;
7676
import com.cloud.utils.db.Filter;
77-
import com.cloud.utils.db.SearchBuilder;
78-
import com.cloud.utils.db.SearchCriteria;
7977
import com.cloud.utils.exception.CloudRuntimeException;
8078
import com.cloud.vm.Nic;
8179
import com.cloud.vm.VirtualMachine;
@@ -119,6 +117,7 @@ private DnsProvider getProviderByType(DnsProviderType type) {
119117
}
120118

121119
@Override
120+
@ActionEvent(eventType = EventTypes.EVENT_DNS_SERVER_ADD, eventDescription = "Adding a DNS Server")
122121
public DnsServer addDnsServer(AddDnsServerCmd cmd) {
123122
Account caller = CallContext.current().getCallingAccount();
124123
DnsServer existing = dnsServerDao.findByUrlAndAccount(cmd.getUrl(), caller.getId());
@@ -139,7 +138,7 @@ public DnsServer addDnsServer(AddDnsServerCmd cmd) {
139138
publicDomainSuffix = DnsProviderUtil.normalizeDomain(publicDomainSuffix);
140139
}
141140

142-
DnsProviderType type = cmd.getProviderType();
141+
DnsProviderType type = cmd.getProvider();
143142
DnsServerVO server = new DnsServerVO(cmd.getName(), cmd.getUrl(), cmd.getPort(), cmd.getExternalServerId(), type,
144143
cmd.getDnsUserName(), cmd.getCredentials(), isDnsPublic, publicDomainSuffix, cmd.getNameServers(),
145144
caller.getAccountId(), caller.getDomainId());
@@ -159,12 +158,15 @@ public DnsServer addDnsServer(AddDnsServerCmd cmd) {
159158
@Override
160159
public ListResponse<DnsServerResponse> listDnsServers(ListDnsServersCmd cmd) {
161160
Pair<List<DnsServerVO>, Integer> result = searchForDnsServerInternal(cmd);
161+
ListResponse<DnsServerResponse> response = new ListResponse<>();
162+
if (result == null) {
163+
return response;
164+
}
162165
List<String> serverIds = new ArrayList<>();
163166
for (DnsServer server : result.first()) {
164167
serverIds.add(server.getUuid());
165168
}
166169
List<DnsServerJoinVO> joinResult = dnsServerJoinDao.listByUuids(serverIds);
167-
ListResponse<DnsServerResponse> response = new ListResponse<>();
168170
List<DnsServerResponse> serverResponses = new ArrayList<>();
169171
for (DnsServerJoinVO server : joinResult) {
170172
serverResponses.add(createDnsServerResponse(server));
@@ -176,64 +178,20 @@ public ListResponse<DnsServerResponse> listDnsServers(ListDnsServersCmd cmd) {
176178
private Pair<List<DnsServerVO>, Integer> searchForDnsServerInternal(ListDnsServersCmd cmd) {
177179
Long dnsServerId = cmd.getId();
178180
Account caller = CallContext.current().getCallingAccount();
179-
Long domainId = cmd.getDomainId();
180-
boolean isRecursive = cmd.isRecursive();
181-
182-
// Step 1: Build ACL search parameters based on caller permissions
183-
List<Long> permittedAccountIds = new ArrayList<>();
184-
Ternary<Long, Boolean, Project.ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(
185-
domainId, isRecursive, null);
186-
accountMgr.buildACLSearchParameters(caller, dnsServerId, cmd.getAccountName(), null, permittedAccountIds,
187-
domainIdRecursiveListProject, cmd.listAll(), false);
188-
189-
domainId = domainIdRecursiveListProject.first();
190-
isRecursive = domainIdRecursiveListProject.second();
191-
Project.ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
192-
Filter searchFilter = new Filter(DnsServerVO.class, ApiConstants.ID, true, cmd.getStartIndex(), cmd.getPageSizeVal());
193-
194-
// Step 2: Search for caller's own DNS servers using standard ACL pattern
195-
SearchBuilder<DnsServerVO> sb = dnsServerDao.createSearchBuilder();
196-
accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccountIds, listProjectResourcesCriteria);
197-
sb.and(ApiConstants.STATE, sb.entity().getState(), SearchCriteria.Op.EQ);
198-
sb.and(ApiConstants.PROVIDER_TYPE, sb.entity().getProviderType(), SearchCriteria.Op.EQ);
199-
sb.done();
200-
201-
SearchCriteria<DnsServerVO> sc = sb.create();
202-
accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccountIds, listProjectResourcesCriteria);
203-
sc.setParameters(ApiConstants.STATE, DnsServer.State.Enabled);
204-
sc.setParameters(ApiConstants.PROVIDER_TYPE, cmd.getProviderType());
205-
206-
Pair<List<DnsServerVO>, Integer> ownServersPair = dnsServerDao.searchAndCount(sc, searchFilter);
207-
List<DnsServerVO> dnsServers = new ArrayList<>(ownServersPair.first());
208-
int count = ownServersPair.second();
209-
if (cmd.getId() == null) {
210-
Set<Long> parentDomainIds = domainDao.getDomainParentIds(caller.getDomainId());
211-
if (!parentDomainIds.isEmpty()) {
212-
SearchBuilder<DnsServerVO> publicSb = dnsServerDao.createSearchBuilder();
213-
publicSb.and(ApiConstants.IS_PUBLIC, publicSb.entity().isPublicServer(), SearchCriteria.Op.EQ);
214-
publicSb.and(ApiConstants.DOMAIN_IDS, publicSb.entity().getDomainId(), SearchCriteria.Op.IN);
215-
publicSb.and(ApiConstants.STATE, publicSb.entity().getState(), SearchCriteria.Op.EQ);
216-
publicSb.and(ApiConstants.PROVIDER_TYPE, publicSb.entity().getProviderType(), SearchCriteria.Op.EQ);
217-
publicSb.done();
218-
SearchCriteria<DnsServerVO> publicSc = publicSb.create();
219-
publicSc.setParameters(ApiConstants.IS_PUBLIC, 1);
220-
publicSc.setParameters(ApiConstants.DOMAIN_IDS, parentDomainIds.toArray());
221-
publicSc.setParameters(ApiConstants.STATE, DnsServer.State.Enabled);
222-
publicSc.setParameters(ApiConstants.PROVIDER_TYPE, cmd.getProviderType());
223-
List<DnsServerVO> publicServers = dnsServerDao.search(publicSc, null);
224-
List<Long> ownServerIds = dnsServers.stream().map(DnsServerVO::getId).collect(Collectors.toList());
225-
for (DnsServerVO publicServer : publicServers) {
226-
if (!ownServerIds.contains(publicServer.getId())) {
227-
dnsServers.add(publicServer);
228-
count++;
229-
}
230-
}
181+
if (dnsServerId != null) {
182+
DnsServerVO dnsServerVO = dnsServerDao.findById(dnsServerId);
183+
if (dnsServerVO == null) {
184+
return null;
231185
}
186+
return new Pair<>(Collections.singletonList(dnsServerVO), 1);
232187
}
233-
return new Pair<>(dnsServers, count);
188+
Set<Long> parentDomainIds = domainDao.getDomainParentIds(caller.getDomainId());
189+
Filter searchFilter = new Filter(DnsServerVO.class, ApiConstants.ID, true, cmd.getStartIndex(), cmd.getPageSizeVal());
190+
return dnsServerDao.searchDnsServer(dnsServerId, caller.getAccountId(), parentDomainIds, cmd.getProviderType(), cmd.getKeyword(), searchFilter);
234191
}
235192

236193
@Override
194+
@ActionEvent(eventType = EventTypes.EVENT_DNS_SERVER_UPDATE, eventDescription = "Updating DNS Server")
237195
public DnsServer updateDnsServer(UpdateDnsServerCmd cmd) {
238196
Long dnsServerId = cmd.getId();
239197
DnsServerVO dnsServer = dnsServerDao.findById(dnsServerId);
@@ -242,7 +200,7 @@ public DnsServer updateDnsServer(UpdateDnsServerCmd cmd) {
242200
}
243201

244202
Account caller = CallContext.current().getCallingAccount();
245-
accountMgr.checkAccess(caller, null, true, dnsServer);
203+
accountMgr.checkAccess(caller, dnsServer);
246204

247205
boolean validationRequired = false;
248206
String originalUrl = dnsServer.getUrl();
@@ -305,18 +263,20 @@ public DnsServer updateDnsServer(UpdateDnsServerCmd cmd) {
305263
}
306264

307265
@Override
266+
@ActionEvent(eventType = EventTypes.EVENT_DNS_SERVER_DELETE, eventDescription = "Deleting DNS Server")
308267
public boolean deleteDnsServer(DeleteDnsServerCmd cmd) {
309268
Long dnsServerId = cmd.getId();
310269
DnsServerVO dnsServer = dnsServerDao.findById(dnsServerId);
311270
if (dnsServer == null) {
312271
throw new InvalidParameterValueException(String.format("DNS server with ID: %s not found.", dnsServerId));
313272
}
314273
Account caller = CallContext.current().getCallingAccount();
315-
accountMgr.checkAccess(caller, null, true, dnsServer);
274+
accountMgr.checkAccess(caller, dnsServer);
316275
return dnsServerDao.remove(dnsServerId);
317276
}
318277

319278
@Override
279+
@ActionEvent(eventType = EventTypes.EVENT_DNS_ZONE_DELETE, eventDescription = "Deleting DNS Zone")
320280
public boolean deleteDnsZone(Long zoneId) {
321281
DnsZoneVO zone = dnsZoneDao.findById(zoneId);
322282
if (zone == null) {
@@ -340,6 +300,7 @@ public boolean deleteDnsZone(Long zoneId) {
340300
}
341301

342302
@Override
303+
@ActionEvent(eventType = EventTypes.EVENT_DNS_ZONE_UPDATE, eventDescription = "Updating DNS Zone")
343304
public DnsZone updateDnsZone(UpdateDnsZoneCmd cmd) {
344305
DnsZoneVO dnsZone = dnsZoneDao.findById(cmd.getId());
345306
if (dnsZone == null) {
@@ -396,7 +357,7 @@ private Pair<List<DnsZoneVO>, Integer> searchForDnsZonesInternal(ListDnsZonesCmd
396357
Account caller = CallContext.current().getCallingAccount();
397358
if (cmd.getDnsServerId() != null) {
398359
DnsServer dnsServer = dnsServerDao.findById(cmd.getDnsServerId());
399-
accountMgr.checkAccess(caller, null, false, dnsServer);
360+
accountMgr.checkAccess(caller, dnsServer);
400361
}
401362
List<Long> ownDnsServerIds = dnsServerDao.listDnsServerIdsByAccountId(caller.getAccountId());
402363
String keyword = cmd.getKeyword();
@@ -408,6 +369,7 @@ private Pair<List<DnsZoneVO>, Integer> searchForDnsZonesInternal(ListDnsZonesCmd
408369
}
409370

410371
@Override
372+
@ActionEvent(eventType = EventTypes.EVENT_DNS_RECORD_CREATE, eventDescription = "Creating DNS Record")
411373
public DnsRecordResponse createDnsRecord(CreateDnsRecordCmd cmd) {
412374
String recordName = StringUtils.trimToEmpty(cmd.getName()).toLowerCase();
413375
if (StringUtils.isBlank(recordName)) {
@@ -436,6 +398,7 @@ public DnsRecordResponse createDnsRecord(CreateDnsRecordCmd cmd) {
436398
}
437399

438400
@Override
401+
@ActionEvent(eventType = EventTypes.EVENT_DNS_RECORD_DELETE, eventDescription = "Deleting DNS Record")
439402
public boolean deleteDnsRecord(DeleteDnsRecordCmd cmd) {
440403
DnsZoneVO zone = dnsZoneDao.findById(cmd.getDnsZoneId());
441404
if (zone == null) {
@@ -651,21 +614,6 @@ public boolean disassociateZoneFromNetwork(DisassociateDnsZoneFromNetworkCmd cmd
651614
return dnsZoneNetworkMapDao.remove(mapping.getId());
652615
}
653616

654-
655-
@Override
656-
public void checkDnsServerPermissions(Account caller, DnsServer server) {
657-
if (caller.getId() == server.getAccountId()) {
658-
return;
659-
}
660-
if (!server.isPublicServer()) {
661-
throw new PermissionDeniedException(caller + "is not allowed to access the DNS server " + server.getName());
662-
}
663-
Account owner = accountMgr.getAccount(server.getAccountId());
664-
if (!domainDao.isChildDomain(caller.getDomainId(), owner.getDomainId())) {
665-
throw new PermissionDeniedException(caller + "is not allowed to access the DNS server " + server.getName());
666-
}
667-
}
668-
669617
@Override
670618
public String processDnsRecordForInstance(VirtualMachine instance, Network network, Nic nic, boolean isAdd) {
671619
long networkId = network.getId();

0 commit comments

Comments
 (0)