diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java index 03f79a59108..798e348e2c3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java @@ -28,9 +28,13 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.DnsServerResponse; import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.dns.DnsProviderType; import org.apache.cloudstack.dns.DnsServer; import org.apache.commons.lang3.BooleanUtils; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.utils.EnumUtils; + @APICommand(name = "addDnsServer", description = "Adds a new external DNS server", responseObject = DnsServerResponse.class, @@ -51,8 +55,8 @@ public class AddDnsServerCmd extends BaseCmd { @Parameter(name = ApiConstants.URL, type = CommandType.STRING, required = true, description = "API URL of the provider") private String url; - @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, required = true, description = "Provider type (e.g., PowerDNS)") - private String provider; + @Parameter(name = ApiConstants.PROVIDER_TYPE, type = CommandType.STRING, required = true, description = "Provider type (e.g., PowerDNS)") + private String providerType; @Parameter(name = ApiConstants.DNS_USER_NAME, type = CommandType.STRING, description = "Username or email associated with the external DNS provider account (used for authentication)") @@ -82,8 +86,9 @@ public class AddDnsServerCmd extends BaseCmd { ///////////////////////////////////////////////////// public String getName() { return name; } + public String getUrl() { return url; } - public String getProvider() { return provider; } + public String getCredentials() { return credentials; } @@ -104,6 +109,15 @@ public class AddDnsServerCmd extends BaseCmd { return nameServers; } + public DnsProviderType getProviderType() { + DnsProviderType dnsProviderType = EnumUtils.getEnumIgnoreCase(DnsProviderType.class, providerType, DnsProviderType.PowerDNS); + if (dnsProviderType == null) { + throw new InvalidParameterValueException(String.format("Invalid value passed for provider type, valid values are: %s", + EnumUtils.listValues(DnsProviderType.values()))); + } + return dnsProviderType; + } + @Override public long getEntityOwnerId() { return CallContext.current().getCallingAccount().getId(); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AssociateDnsZoneToNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AssociateDnsZoneToNetworkCmd.java index 60f9c70c9c9..53c697db9f2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AssociateDnsZoneToNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AssociateDnsZoneToNetworkCmd.java @@ -18,6 +18,8 @@ package org.apache.cloudstack.api.command.user.dns; import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.acl.SecurityChecker; +import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -27,12 +29,14 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.DnsZoneNetworkMapResponse; import org.apache.cloudstack.api.response.DnsZoneResponse; import org.apache.cloudstack.api.response.NetworkResponse; +import org.apache.cloudstack.dns.DnsZone; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.user.Account; @APICommand(name = "associateDnsZoneToNetwork", description = "Associates a DNS Zone with a Network for VM auto-registration", @@ -47,6 +51,7 @@ public class AssociateDnsZoneToNetworkCmd extends BaseCmd { required = true, description = "The ID of the DNS zone") private Long dnsZoneId; + @ACL(accessType = SecurityChecker.AccessType.OperateEntry) @Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, required = true, description = "The ID of the network") private Long networkId; @@ -68,7 +73,11 @@ public class AssociateDnsZoneToNetworkCmd extends BaseCmd { @Override public long getEntityOwnerId() { - return dnsProviderManager.getDnsZone(dnsZoneId).getAccountId(); + DnsZone zone = _entityMgr.findById(DnsZone.class, dnsZoneId); + if (zone != null) { + return zone.getAccountId(); + } + return Account.ACCOUNT_ID_SYSTEM; } public Long getDnsZoneId() { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/DeleteDnsZoneCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/DeleteDnsZoneCmd.java index 88b3713fe2e..fa8319a5ea2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/DeleteDnsZoneCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/DeleteDnsZoneCmd.java @@ -80,8 +80,7 @@ public class DeleteDnsZoneCmd extends BaseAsyncCmd { @Override public long getEntityOwnerId() { - // Look up the Zone to find the Account Owner - DnsZone zone = dnsProviderManager.getDnsZone(id); + DnsZone zone = _entityMgr.findById(DnsZone.class, id); if (zone != null) { return zone.getAccountId(); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/DisassociateDnsZoneFromNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/DisassociateDnsZoneFromNetworkCmd.java index bd31737d30e..80db66c0ec0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/DisassociateDnsZoneFromNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/DisassociateDnsZoneFromNetworkCmd.java @@ -26,7 +26,8 @@ import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.DnsZoneNetworkMapResponse; +import org.apache.cloudstack.api.response.DnsZoneResponse; +import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.SuccessResponse; import com.cloud.exception.ConcurrentOperationException; @@ -44,10 +45,14 @@ import com.cloud.user.Account; authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class DisassociateDnsZoneFromNetworkCmd extends BaseCmd { + @Parameter(name = ApiConstants.DNS_ZONE_ID, type = CommandType.UUID, entityType = DnsZoneResponse.class, + required = true, description = "The ID of the DNS zone") + private Long dnsZoneId; + @ACL(accessType = SecurityChecker.AccessType.OperateEntry) - @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = DnsZoneNetworkMapResponse.class, - required = true, description = "The ID of the DNS zone to network mapping") - private Long id; + @Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, + required = true, description = "The ID of the network") + private Long networkId; @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { @@ -69,5 +74,11 @@ public class DisassociateDnsZoneFromNetworkCmd extends BaseCmd { return Account.ACCOUNT_ID_SYSTEM; } - public Long getId() { return id; } + public Long getDnsZoneId() { + return dnsZoneId; + } + + public void setDnsZoneId(Long dnsZoneId) { + this.dnsZoneId = dnsZoneId; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/ListDnsServersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/ListDnsServersCmd.java index 39cb24a3ec3..ca7ac1944a9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/ListDnsServersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/ListDnsServersCmd.java @@ -24,8 +24,12 @@ import org.apache.cloudstack.api.BaseListAccountResourcesCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.DnsServerResponse; import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.dns.DnsProviderType; import org.apache.cloudstack.dns.DnsServer; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.utils.EnumUtils; + @APICommand(name = "listDnsServers", description = "Lists DNS servers owned by the account.", responseObject = DnsServerResponse.class, @@ -43,9 +47,9 @@ public class ListDnsServersCmd extends BaseListAccountResourcesCmd { description = "the ID of the DNS server") private Long id; - @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, + @Parameter(name = ApiConstants.PROVIDER_TYPE, type = CommandType.STRING, description = "filter by provider type (e.g. PowerDNS, Cloudflare)") - private String provider; + private String providerType; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -55,8 +59,13 @@ public class ListDnsServersCmd extends BaseListAccountResourcesCmd { return id; } - public String getProvider() { - return provider; + public DnsProviderType getProviderType() { + DnsProviderType dnsProviderType = EnumUtils.getEnumIgnoreCase(DnsProviderType.class, providerType, DnsProviderType.PowerDNS); + if (dnsProviderType == null) { + throw new InvalidParameterValueException(String.format("Invalid value passed for provider type, valid values are: %s", + EnumUtils.listValues(DnsProviderType.values()))); + } + return dnsProviderType; } ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/ListDnsZonesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/ListDnsZonesCmd.java index 7d6f17a28f0..e71bdabaf61 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/ListDnsZonesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/ListDnsZonesCmd.java @@ -20,7 +20,7 @@ package org.apache.cloudstack.api.command.user.dns; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseListAccountResourcesCmd; +import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.DnsServerResponse; import org.apache.cloudstack.api.response.DnsZoneResponse; @@ -33,7 +33,7 @@ import org.apache.cloudstack.dns.DnsZone; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.23.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) -public class ListDnsZonesCmd extends BaseListAccountResourcesCmd { +public class ListDnsZonesCmd extends BaseListCmd { ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/RegisterDnsRecordForVmCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/RegisterDnsRecordForVmCmd.java deleted file mode 100644 index 935c78e85fb..00000000000 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/RegisterDnsRecordForVmCmd.java +++ /dev/null @@ -1,80 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.apache.cloudstack.api.command.user.dns; - -import org.apache.cloudstack.acl.RoleType; -import org.apache.cloudstack.api.ACL; -import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseCmd; -import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.NetworkResponse; -import org.apache.cloudstack.api.response.SuccessResponse; -import org.apache.cloudstack.api.response.UserVmResponse; -import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.dns.DnsRecord; - -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.NetworkRuleConflictException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; - -@APICommand(name = "registerDnsRecordForVm", - description = "Automatically registers a DNS record for a VM based on its associated Network and DNS Zone mapping", - responseObject = SuccessResponse.class, - entityType = {DnsRecord.class}, - since = "4.23.0", - authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) -public class RegisterDnsRecordForVmCmd extends BaseCmd { - - @ACL - @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, - required = true, description = "The ID of the Virtual Machine") - private Long vmId; - - @ACL - @Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, - description = "The ID of the network. If not specified, the VM's default NIC network is used.") - private Long networkId; - - public Long getVmId() { return vmId; } - public Long getNetworkId() { return networkId; } - - @Override - public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { - try { - boolean result = dnsProviderManager.registerDnsRecordForVm(this); - if (result) { - SuccessResponse response = new SuccessResponse(getCommandName()); - setResponseObject(response); - } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to register DNS record for VM"); - } - } catch (Exception e) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); - } - } - - @Override - public long getEntityOwnerId() { - return CallContext.current().getCallingAccountId(); - } -} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/RemoveDnsRecordForVmCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/RemoveDnsRecordForVmCmd.java deleted file mode 100644 index 0d1adf7cfb0..00000000000 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/RemoveDnsRecordForVmCmd.java +++ /dev/null @@ -1,83 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.apache.cloudstack.api.command.user.dns; - -import org.apache.cloudstack.acl.RoleType; -import org.apache.cloudstack.api.ACL; -import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseCmd; -import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.NetworkResponse; -import org.apache.cloudstack.api.response.SuccessResponse; -import org.apache.cloudstack.api.response.UserVmResponse; -import org.apache.cloudstack.context.CallContext; - -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.NetworkRuleConflictException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; - -@APICommand(name = "removeDnsRecordForVm", - description = "Removes the auto-registered DNS record for a VM", - responseObject = SuccessResponse.class, - since = "4.23.0", - authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) -public class RemoveDnsRecordForVmCmd extends BaseCmd { - - @ACL - @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, - required = true, description = "The ID of the Virtual Machine") - private Long vmId; - - @ACL - @Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, - description = "The ID of the network. If not specified, the VM's default NIC network is used.") - private Long networkId; - - public Long getVmId() { - return vmId; - } - - public Long getNetworkId() { - return networkId; - } - - @Override - public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { - try { - boolean result = dnsProviderManager.removeDnsRecordForVm(this); - if (result) { - SuccessResponse response = new SuccessResponse(getCommandName()); - setResponseObject(response); - } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove DNS record for VM"); - } - } catch (Exception e) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); - } - } - - @Override - public long getEntityOwnerId() { - return CallContext.current().getCallingAccountId(); - } -} diff --git a/api/src/main/java/org/apache/cloudstack/dns/DnsProvider.java b/api/src/main/java/org/apache/cloudstack/dns/DnsProvider.java index 852df8dd0bf..809dad4f647 100644 --- a/api/src/main/java/org/apache/cloudstack/dns/DnsProvider.java +++ b/api/src/main/java/org/apache/cloudstack/dns/DnsProvider.java @@ -24,6 +24,7 @@ import org.apache.cloudstack.dns.exception.DnsProviderException; import com.cloud.utils.component.Adapter; public interface DnsProvider extends Adapter { + DnsProviderType getProviderType(); // Validates connectivity to the server diff --git a/api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java b/api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java index 72a793328af..e3db63a3531 100644 --- a/api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java +++ b/api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java @@ -29,8 +29,6 @@ import org.apache.cloudstack.api.command.user.dns.DisassociateDnsZoneFromNetwork import org.apache.cloudstack.api.command.user.dns.ListDnsRecordsCmd; import org.apache.cloudstack.api.command.user.dns.ListDnsServersCmd; import org.apache.cloudstack.api.command.user.dns.ListDnsZonesCmd; -import org.apache.cloudstack.api.command.user.dns.RegisterDnsRecordForVmCmd; -import org.apache.cloudstack.api.command.user.dns.RemoveDnsRecordForVmCmd; import org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd; import org.apache.cloudstack.api.command.user.dns.UpdateDnsZoneCmd; import org.apache.cloudstack.api.response.DnsRecordResponse; @@ -56,7 +54,6 @@ public interface DnsProviderManager extends Manager, PluggableService { // Calls the Plugin (State: Inactive -> Active) DnsZone provisionDnsZone(long zoneId); - DnsZone getDnsZone(Long id); DnsZone updateDnsZone(UpdateDnsZoneCmd cmd); boolean deleteDnsZone(Long id); ListResponse listDnsZones(ListDnsZonesCmd cmd); @@ -75,9 +72,5 @@ public interface DnsProviderManager extends Manager, PluggableService { boolean disassociateZoneFromNetwork(DisassociateDnsZoneFromNetworkCmd cmd); - boolean registerDnsRecordForVm(RegisterDnsRecordForVmCmd cmd); - boolean removeDnsRecordForVm(RemoveDnsRecordForVmCmd cmd); - void checkDnsServerPermissions(Account caller, DnsServer server); - void checkDnsZonePermission(Account caller, DnsZone zone); } diff --git a/api/src/main/java/org/apache/cloudstack/dns/DnsProviderType.java b/api/src/main/java/org/apache/cloudstack/dns/DnsProviderType.java index 0b8f88d6745..23c8e936613 100644 --- a/api/src/main/java/org/apache/cloudstack/dns/DnsProviderType.java +++ b/api/src/main/java/org/apache/cloudstack/dns/DnsProviderType.java @@ -20,15 +20,4 @@ package org.apache.cloudstack.dns; public enum DnsProviderType { PowerDNS; // Cloudflare - - // Helper to validate and return Enum from String safely - public static DnsProviderType fromString(String type) { - if (type == null) return null; - for (DnsProviderType t : DnsProviderType.values()) { - if (t.name().equalsIgnoreCase(type)) { - return t; - } - } - throw new IllegalArgumentException("Invalid DNS Provider type: " + type); - } } diff --git a/server/src/main/java/com/cloud/acl/DomainChecker.java b/server/src/main/java/com/cloud/acl/DomainChecker.java index ba4f5e53031..b9a017fd4ee 100644 --- a/server/src/main/java/com/cloud/acl/DomainChecker.java +++ b/server/src/main/java/com/cloud/acl/DomainChecker.java @@ -27,16 +27,15 @@ import org.apache.cloudstack.acl.ProjectRoleService; import org.apache.cloudstack.acl.RolePermissionEntity; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.affinity.AffinityGroup; +import org.apache.cloudstack.backup.BackupOffering; +import org.apache.cloudstack.backup.dao.BackupOfferingDetailsDao; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.dns.DnsProviderManager; import org.apache.cloudstack.dns.DnsServer; -import org.apache.cloudstack.dns.DnsZone; import org.apache.cloudstack.query.QueryService; import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao; import org.springframework.stereotype.Component; -import org.apache.cloudstack.backup.dao.BackupOfferingDetailsDao; -import org.apache.cloudstack.backup.BackupOffering; import com.cloud.dc.DataCenter; import com.cloud.dc.DedicatedResourceVO; import com.cloud.dc.dao.DedicatedResourceDao; @@ -223,10 +222,7 @@ public class DomainChecker extends AdapterBase implements SecurityChecker { return false; } else if (entity instanceof DnsServer) { dnsProviderManager.checkDnsServerPermissions(caller, (DnsServer) entity); - } else if (entity instanceof DnsZone) { - dnsProviderManager.checkDnsZonePermission(caller, (DnsZone) entity); - } - else { + } else { validateCallerHasAccessToEntityOwner(caller, entity, accessType); } return true; diff --git a/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java b/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java index b79a59342df..5e70ec3c1f7 100644 --- a/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java @@ -20,6 +20,7 @@ package org.apache.cloudstack.dns; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import javax.inject.Inject; @@ -37,8 +38,6 @@ import org.apache.cloudstack.api.command.user.dns.ListDnsProvidersCmd; import org.apache.cloudstack.api.command.user.dns.ListDnsRecordsCmd; import org.apache.cloudstack.api.command.user.dns.ListDnsServersCmd; import org.apache.cloudstack.api.command.user.dns.ListDnsZonesCmd; -import org.apache.cloudstack.api.command.user.dns.RegisterDnsRecordForVmCmd; -import org.apache.cloudstack.api.command.user.dns.RemoveDnsRecordForVmCmd; import org.apache.cloudstack.api.command.user.dns.UpdateDnsServerCmd; import org.apache.cloudstack.api.command.user.dns.UpdateDnsZoneCmd; import org.apache.cloudstack.api.response.DnsRecordResponse; @@ -55,7 +54,6 @@ import org.apache.cloudstack.dns.vo.DnsZoneNetworkMapVO; import org.apache.cloudstack.dns.vo.DnsZoneVO; import org.springframework.stereotype.Component; -import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; @@ -98,7 +96,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa @Inject DomainDao domainDao; - private DnsProvider getProvider(DnsProviderType type) { + private DnsProvider getProviderByType(DnsProviderType type) { if (type == null) { throw new CloudRuntimeException("Provider type cannot be null"); } @@ -131,13 +129,13 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa publicDomainSuffix = DnsProviderUtil.normalizeDomain(publicDomainSuffix); } - DnsProviderType type = DnsProviderType.fromString(cmd.getProvider()); + DnsProviderType type = cmd.getProviderType(); DnsServerVO server = new DnsServerVO(cmd.getName(), cmd.getUrl(), cmd.getPort(), cmd.getExternalServerId(), type, cmd.getDnsUserName(), cmd.getCredentials(), isDnsPublic, publicDomainSuffix, cmd.getNameServers(), caller.getAccountId(), caller.getDomainId()); try { - DnsProvider provider = getProvider(type); - String dnsServerId = provider.validateAndResolveServer(server); // localhost for PowerDNS + DnsProvider provider = getProviderByType(type); + String dnsServerId = provider.validateAndResolveServer(server); // returns localhost for PowerDNS if (StringUtils.isNotBlank(dnsServerId)) { server.setExternalServerId(dnsServerId); } @@ -176,57 +174,51 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa domainId = domainIdRecursiveListProject.first(); isRecursive = domainIdRecursiveListProject.second(); Project.ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - Filter searchFilter = new Filter(DnsServerVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); + Filter searchFilter = new Filter(DnsServerVO.class, ApiConstants.ID, true, cmd.getStartIndex(), cmd.getPageSizeVal()); // Step 2: Search for caller's own DNS servers using standard ACL pattern SearchBuilder sb = dnsServerDao.createSearchBuilder(); accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccountIds, listProjectResourcesCriteria); - sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); + sb.and(ApiConstants.STATE, sb.entity().getState(), SearchCriteria.Op.EQ); + sb.and(ApiConstants.PROVIDER_TYPE, sb.entity().getProviderType(), SearchCriteria.Op.EQ); sb.done(); SearchCriteria sc = sb.create(); accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccountIds, listProjectResourcesCriteria); - sc.setParameters("state", DnsServer.State.Enabled); + sc.setParameters(ApiConstants.STATE, DnsServer.State.Enabled); + if (cmd.getProviderType() != null) { + sc.setParameters(ApiConstants.PROVIDER_TYPE, cmd.getProviderType()); + } Pair, Integer> ownServersPair = dnsServerDao.searchAndCount(sc, searchFilter); List dnsServers = new ArrayList<>(ownServersPair.first()); int count = ownServersPair.second(); - - // Step 3: Search for public DNS servers from caller's domain and children - // domains - Long callerDomainId = caller.getDomainId(); - DomainVO callerDomain = domainDao.findById(callerDomainId); - if (callerDomain != null) { - List domainIds = new ArrayList<>(); - domainIds.add(callerDomainId); - List childDomains = domainDao.findAllChildren(callerDomain.getPath(), callerDomainId); - for (DomainVO childDomain : childDomains) { - domainIds.add(childDomain.getId()); - } - - SearchBuilder publicSb = dnsServerDao.createSearchBuilder(); - publicSb.and("publicDns", publicSb.entity().isPublicServer(), SearchCriteria.Op.EQ); - publicSb.and("publicDomainId", publicSb.entity().getDomainId(), SearchCriteria.Op.IN); - publicSb.and("publicState", publicSb.entity().getState(), SearchCriteria.Op.EQ); - publicSb.done(); - - SearchCriteria publicSc = publicSb.create(); - publicSc.setParameters("publicDns", 1); - publicSc.setParameters("publicDomainId", domainIds.toArray()); - publicSc.setParameters("publicState", DnsServer.State.Enabled); - - List publicServers = dnsServerDao.search(publicSc, null); - - // Deduplicate: add only public servers not already in the own servers list - List ownServerIds = dnsServers.stream().map(DnsServerVO::getId).collect(Collectors.toList()); - for (DnsServerVO publicServer : publicServers) { - if (!ownServerIds.contains(publicServer.getId())) { - dnsServers.add(publicServer); - count++; + if (cmd.getId() == null) { + Set parentDomainIds = domainDao.getDomainParentIds(caller.getDomainId()); + if (!parentDomainIds.isEmpty()) { + SearchBuilder publicSb = dnsServerDao.createSearchBuilder(); + publicSb.and(ApiConstants.IS_PUBLIC, publicSb.entity().isPublicServer(), SearchCriteria.Op.EQ); + publicSb.and(ApiConstants.DOMAIN_IDS, publicSb.entity().getDomainId(), SearchCriteria.Op.IN); + publicSb.and(ApiConstants.STATE, publicSb.entity().getState(), SearchCriteria.Op.EQ); + publicSb.and(ApiConstants.PROVIDER_TYPE, publicSb.entity().getProviderType(), SearchCriteria.Op.EQ); + publicSb.done(); + SearchCriteria publicSc = publicSb.create(); + publicSc.setParameters(ApiConstants.IS_PUBLIC, 1); + publicSc.setParameters(ApiConstants.DOMAIN_IDS, parentDomainIds.toArray()); + publicSc.setParameters(ApiConstants.STATE, DnsServer.State.Enabled); + if (cmd.getProviderType() != null) { + publicSc.setParameters(ApiConstants.PROVIDER_TYPE, cmd.getProviderType()); + } + List publicServers = dnsServerDao.search(publicSc, null); + List ownServerIds = dnsServers.stream().map(DnsServerVO::getId).collect(Collectors.toList()); + for (DnsServerVO publicServer : publicServers) { + if (!ownServerIds.contains(publicServer.getId())) { + dnsServers.add(publicServer); + count++; + } } } } - return new Pair<>(dnsServers, count); } @@ -284,7 +276,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa } if (validationRequired) { - DnsProvider provider = getProvider(dnsServer.getProviderType()); + DnsProvider provider = getProviderByType(dnsServer.getProviderType()); try { provider.validate(dnsServer); } catch (Exception ex) { @@ -340,7 +332,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa DnsServerVO server = dnsServerDao.findById(zone.getDnsServerId()); if (server != null && zone.getState() == DnsZone.State.Active) { try { - DnsProvider provider = getProvider(server.getProviderType()); + DnsProvider provider = getProviderByType(server.getProviderType()); provider.deleteZone(server, zone); logger.debug("Deleted DNS zone: {}", zone.getName()); } catch (Exception ex) { @@ -351,11 +343,6 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa return dnsZoneDao.remove(zoneId); } - @Override - public DnsZone getDnsZone(Long id) { - return dnsZoneDao.findById(id); - } - @Override public DnsZone updateDnsZone(UpdateDnsZoneCmd cmd) { DnsZoneVO dnsZone = dnsZoneDao.findById(cmd.getId()); @@ -376,7 +363,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa throw new CloudRuntimeException("The underlying DNS server for this DNS zone is missing."); } try { - DnsProvider provider = getProvider(server.getProviderType()); + DnsProvider provider = getProviderByType(server.getProviderType()); provider.updateZone(server, dnsZone); } catch (Exception ex) { logger.error("Failed to update DNS zone: {} on DNS server: {}", dnsZone.getName(), server.getName(), ex); @@ -438,7 +425,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa List normalizedContents = cmd.getContents().stream() .map(value -> DnsProviderUtil.normalizeDnsRecordValue(value, type)).collect(Collectors.toList()); DnsRecord record = new DnsRecord(recordName, type, normalizedContents, cmd.getTtl()); - DnsProvider provider = getProvider(server.getProviderType()); + DnsProvider provider = getProviderByType(server.getProviderType()); String normalizedRecordName = provider.addRecord(server, zone, record); record.setName(normalizedRecordName); return createDnsRecordResponse(record); @@ -465,7 +452,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa DnsRecord record = new DnsRecord(); record.setName(cmd.getName()); record.setType(cmd.getType()); - DnsProvider provider = getProvider(server.getProviderType()); + DnsProvider provider = getProviderByType(server.getProviderType()); provider.deleteRecord(server, zone, record); return true; } catch (Exception ex) { @@ -487,7 +474,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa throw new CloudRuntimeException("The underlying DNS server for this DNS zone is missing."); } try { - DnsProvider provider = getProvider(server.getProviderType()); + DnsProvider provider = getProviderByType(server.getProviderType()); List records = provider.listRecords(server, zone); List responses = new ArrayList<>(); for (DnsRecord record : records) { @@ -550,7 +537,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa } DnsServerVO server = dnsServerDao.findById(dnsZone.getDnsServerId()); try { - DnsProvider provider = getProvider(server.getProviderType()); + DnsProvider provider = getProviderByType(server.getProviderType()); String externalReferenceId = provider.provisionZone(server, dnsZone); dnsZone.setExternalReference(externalReferenceId); dnsZone.setState(DnsZone.State.Active); @@ -619,7 +606,8 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa @Override public boolean disassociateZoneFromNetwork(DisassociateDnsZoneFromNetworkCmd cmd) { - DnsZoneNetworkMapVO mapping = dnsZoneNetworkMapDao.findById(cmd.getId()); + // fix this method + DnsZoneNetworkMapVO mapping = dnsZoneNetworkMapDao.findById(cmd.getDnsZoneId()); if (mapping == null) { throw new InvalidParameterValueException("The specified DNS zone to network mapping does not exist."); } @@ -634,15 +622,6 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa return dnsZoneNetworkMapDao.remove(mapping.getId()); } - @Override - public boolean registerDnsRecordForVm(RegisterDnsRecordForVmCmd cmd) { - return processDnsRecordForInstance(cmd.getVmId(), cmd.getNetworkId(), true); - } - - @Override - public boolean removeDnsRecordForVm(RemoveDnsRecordForVmCmd cmd) { - return processDnsRecordForInstance(cmd.getVmId(), cmd.getNetworkId(), false); - } @Override public void checkDnsServerPermissions(Account caller, DnsServer server) { @@ -653,18 +632,11 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa throw new PermissionDeniedException(caller + "is not allowed to access the DNS server " + server.getName()); } Account owner = accountMgr.getAccount(server.getAccountId()); - if (!domainDao.isChildDomain(owner.getDomainId(), caller.getDomainId())) { + if (!domainDao.isChildDomain(caller.getDomainId(), owner.getDomainId())) { throw new PermissionDeniedException(caller + "is not allowed to access the DNS server " + server.getName()); } } - @Override - public void checkDnsZonePermission(Account caller, DnsZone zone) { - if (caller.getId() != zone.getAccountId()) { - throw new PermissionDeniedException(caller + "is not allowed to access the DNS Zone " + zone.getName()); - } - } - /** * Helper method to handle both Register and Remove logic for Instance */ @@ -716,7 +688,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa } try { - DnsProvider provider = getProvider(server.getProviderType()); + DnsProvider provider = getProviderByType(server.getProviderType()); // Handle IPv4 (A Record) if (nic.getIPv4Address() != null) { DnsRecord recordA = new DnsRecord(recordName, DnsRecord.RecordType.A, Collections.singletonList(nic.getIPv4Address()), 3600); @@ -789,8 +761,6 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa cmdList.add(CreateDnsRecordCmd.class); cmdList.add(ListDnsRecordsCmd.class); cmdList.add(DeleteDnsRecordCmd.class); - cmdList.add(RegisterDnsRecordForVmCmd.class); - cmdList.add(RemoveDnsRecordForVmCmd.class); return cmdList; } diff --git a/server/src/main/java/org/apache/cloudstack/dns/dao/DnsServerDaoImpl.java b/server/src/main/java/org/apache/cloudstack/dns/dao/DnsServerDaoImpl.java index 8a7311e2f1a..655cdf9a3e8 100644 --- a/server/src/main/java/org/apache/cloudstack/dns/dao/DnsServerDaoImpl.java +++ b/server/src/main/java/org/apache/cloudstack/dns/dao/DnsServerDaoImpl.java @@ -56,6 +56,7 @@ public class DnsServerDaoImpl extends GenericDaoBase implemen DnsServerIdsByAccountSearch = createSearchBuilder(Long.class); DnsServerIdsByAccountSearch.selectFields(DnsServerIdsByAccountSearch.entity().getId()); DnsServerIdsByAccountSearch.and(ApiConstants.ACCOUNT_ID, DnsServerIdsByAccountSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + DnsServerIdsByAccountSearch.and(ApiConstants.STATE, DnsServerIdsByAccountSearch.entity().getState(), SearchCriteria.Op.EQ); DnsServerIdsByAccountSearch.done(); } @@ -74,6 +75,7 @@ public class DnsServerDaoImpl extends GenericDaoBase implemen if (accountId != null) { sc.setParameters(ApiConstants.ACCOUNT_ID, accountId); } + sc.setParameters(ApiConstants.STATE, DnsServer.State.Enabled); return customSearch(sc, null); } diff --git a/server/src/main/java/org/apache/cloudstack/dns/dao/DnsZoneDaoImpl.java b/server/src/main/java/org/apache/cloudstack/dns/dao/DnsZoneDaoImpl.java index 9ad1217cb71..1aad6fa0f0b 100644 --- a/server/src/main/java/org/apache/cloudstack/dns/dao/DnsZoneDaoImpl.java +++ b/server/src/main/java/org/apache/cloudstack/dns/dao/DnsZoneDaoImpl.java @@ -35,7 +35,6 @@ import com.cloud.utils.db.SearchCriteria; public class DnsZoneDaoImpl extends GenericDaoBase implements DnsZoneDao { SearchBuilder AccountSearch; SearchBuilder NameServerTypeSearch; - SearchBuilder AllFieldsSearch; public DnsZoneDaoImpl() { super(); @@ -51,16 +50,6 @@ public class DnsZoneDaoImpl extends GenericDaoBase implements D NameServerTypeSearch.and(ApiConstants.TYPE, NameServerTypeSearch.entity().getType(), SearchCriteria.Op.EQ); NameServerTypeSearch.and(ApiConstants.STATE, NameServerTypeSearch.entity().getState(), SearchCriteria.Op.EQ); NameServerTypeSearch.done(); - - AllFieldsSearch = createSearchBuilder(); - AllFieldsSearch.and().op(ApiConstants.DNS_SERVER_ID, AllFieldsSearch.entity().getDnsServerId(), SearchCriteria.Op.IN); - AllFieldsSearch.or(ApiConstants.ACCOUNT_ID, AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ); - AllFieldsSearch.cp(); - AllFieldsSearch.and(ApiConstants.STATE, AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ); - AllFieldsSearch.and(ApiConstants.ID, AllFieldsSearch.entity().getId(), SearchCriteria.Op.EQ); - AllFieldsSearch.and(ApiConstants.NAME, AllFieldsSearch.entity().getName(), SearchCriteria.Op.LIKE); - AllFieldsSearch.and(ApiConstants.TARGET_ID, AllFieldsSearch.entity().getDnsServerId(), SearchCriteria.Op.EQ); - AllFieldsSearch.done(); } @Override @@ -85,7 +74,21 @@ public class DnsZoneDaoImpl extends GenericDaoBase implements D public Pair, Integer> searchZones(Long id, Long accountId, List ownDnsServerIds, Long targetDnsServerId, String keyword, Filter filter) { - SearchCriteria sc = AllFieldsSearch.create(); + SearchBuilder sb = createSearchBuilder(); + sb.and(ApiConstants.STATE, sb.entity().getState(), SearchCriteria.Op.EQ); + sb.and(ApiConstants.ID, sb.entity().getId(), SearchCriteria.Op.EQ); + sb.and(ApiConstants.NAME, sb.entity().getName(), SearchCriteria.Op.LIKE); + sb.and(ApiConstants.TARGET_ID, sb.entity().getDnsServerId(), SearchCriteria.Op.EQ); + if (!CollectionUtils.isEmpty(ownDnsServerIds)) { + sb.and().op(ApiConstants.DNS_SERVER_ID, sb.entity().getDnsServerId(), SearchCriteria.Op.IN); + sb.or(ApiConstants.ACCOUNT_ID, sb.entity().getAccountId(), SearchCriteria.Op.EQ); + sb.cp(); + } else { + sb.and(ApiConstants.ACCOUNT_ID, sb.entity().getAccountId(), SearchCriteria.Op.EQ); + } + sb.done(); + + SearchCriteria sc = sb.create(); if (id != null) { sc.setParameters(ApiConstants.ID, id); }