2
0
mirror of https://github.com/VinylDNS/vinyldns synced 2025-08-22 10:10:12 +00:00

Address PR comments

This commit is contained in:
Aravindh-Raju 2022-10-12 11:37:35 +05:30
parent 843dcf20e5
commit adb933a783
No known key found for this signature in database
GPG Key ID: 6B4D566AC36626F6
7 changed files with 142 additions and 81 deletions

View File

@ -19,13 +19,13 @@ package vinyldns.api.config
import pureconfig.ConfigReader import pureconfig.ConfigReader
import pureconfig.generic.auto._ import pureconfig.generic.auto._
final case class AuthConfigs(zone: String, allowedUserList: List[String], allowedGroupList: List[String], allowedRecordType: List[String], allowedDotsLimit: Int) final case class ZoneAuthConfigs(zone: String, allowedUserList: List[String], allowedGroupList: List[String], allowedRecordType: List[String], allowedDotsLimit: Int)
final case class DottedHostsConfig(authConfigs: List[AuthConfigs]) final case class DottedHostsConfig(zoneAuthConfigs: List[ZoneAuthConfigs])
object DottedHostsConfig { object DottedHostsConfig {
implicit val configReader: ConfigReader[DottedHostsConfig] = implicit val configReader: ConfigReader[DottedHostsConfig] =
ConfigReader.forProduct1[DottedHostsConfig, List[AuthConfigs]]( ConfigReader.forProduct1[DottedHostsConfig, List[ZoneAuthConfigs]](
"allowed-settings", "allowed-settings",
)(authConfigs => )(zoneAuthConfigs =>
DottedHostsConfig(authConfigs)) DottedHostsConfig(zoneAuthConfigs))
} }

View File

@ -28,7 +28,7 @@ import vinyldns.core.queue.MessageQueue
import cats.data._ import cats.data._
import cats.effect.IO import cats.effect.IO
import org.xbill.DNS.ReverseMap import org.xbill.DNS.ReverseMap
import vinyldns.api.config.{AuthConfigs, DottedHostsConfig, HighValueDomainConfig} import vinyldns.api.config.{ZoneAuthConfigs, DottedHostsConfig, HighValueDomainConfig}
import vinyldns.api.domain.DomainValidations.{validateIpv4Address, validateIpv6Address} import vinyldns.api.domain.DomainValidations.{validateIpv4Address, validateIpv6Address}
import vinyldns.api.domain.access.AccessValidationsAlgebra import vinyldns.api.domain.access.AccessValidationsAlgebra
import vinyldns.core.domain.record.NameSort.NameSort import vinyldns.core.domain.record.NameSort.NameSort
@ -91,7 +91,7 @@ class RecordSetService(
def addRecordSet(recordSet: RecordSet, auth: AuthPrincipal): Result[ZoneCommandResult] = def addRecordSet(recordSet: RecordSet, auth: AuthPrincipal): Result[ZoneCommandResult] =
for { for {
zone <- getZone(recordSet.zoneId) zone <- getZone(recordSet.zoneId)
authZones = dottedHostsConfig.authConfigs.map(x => x.zone) authZones = dottedHostsConfig.zoneAuthConfigs.map(x => x.zone)
change <- RecordSetChangeGenerator.forAdd(recordSet, zone, Some(auth)).toResult change <- RecordSetChangeGenerator.forAdd(recordSet, zone, Some(auth)).toResult
// because changes happen to the RS in forAdd itself, converting 1st and validating on that // because changes happen to the RS in forAdd itself, converting 1st and validating on that
rsForValidations = change.recordSet rsForValidations = change.recordSet
@ -127,7 +127,8 @@ class RecordSetService(
approvedNameServers, approvedNameServers,
recordFqdnDoesNotAlreadyExist, recordFqdnDoesNotAlreadyExist,
allowedZoneList, allowedZoneList,
isRecordTypeAndUserAllowed isRecordTypeAndUserAllowed,
allowedDotsLimit
).toResult ).toResult
_ <- if(allowedZoneList.contains(zone.name)) checkAllowedDots(allowedDotsLimit, rsForValidations, zone).toResult else ().toResult _ <- if(allowedZoneList.contains(zone.name)) checkAllowedDots(allowedDotsLimit, rsForValidations, zone).toResult else ().toResult
_ <- if(allowedZoneList.contains(zone.name)) isNotApexEndsWithDot(rsForValidations, zone).toResult else ().toResult _ <- if(allowedZoneList.contains(zone.name)) isNotApexEndsWithDot(rsForValidations, zone).toResult else ().toResult
@ -160,7 +161,7 @@ class RecordSetService(
validateRecordLookupAgainstDnsBackend validateRecordLookupAgainstDnsBackend
) )
_ <- noCnameWithNewName(rsForValidations, existingRecordsWithName, zone).toResult _ <- noCnameWithNewName(rsForValidations, existingRecordsWithName, zone).toResult
authZones = dottedHostsConfig.authConfigs.map(x => x.zone) authZones = dottedHostsConfig.zoneAuthConfigs.map(x => x.zone)
allowedZoneList <- getAllowedZones(authZones).toResult[Set[String]] allowedZoneList <- getAllowedZones(authZones).toResult[Set[String]]
isInAllowedUsers = checkIfInAllowedUsers(zone, dottedHostsConfig, auth) isInAllowedUsers = checkIfInAllowedUsers(zone, dottedHostsConfig, auth)
isUserInAllowedGroups <- checkIfInAllowedGroups(zone, dottedHostsConfig, auth).toResult[Boolean] isUserInAllowedGroups <- checkIfInAllowedGroups(zone, dottedHostsConfig, auth).toResult[Boolean]
@ -178,6 +179,7 @@ class RecordSetService(
recordFqdnDoesNotAlreadyExist, recordFqdnDoesNotAlreadyExist,
allowedZoneList, allowedZoneList,
isRecordTypeAndUserAllowed, isRecordTypeAndUserAllowed,
allowedDotsLimit
).toResult ).toResult
_ <- if(existing.name == rsForValidations.name) ().toResult else if(allowedZoneList.contains(zone.name)) checkAllowedDots(allowedDotsLimit, rsForValidations, zone).toResult else ().toResult _ <- if(existing.name == rsForValidations.name) ().toResult else if(allowedZoneList.contains(zone.name)) checkAllowedDots(allowedDotsLimit, rsForValidations, zone).toResult else ().toResult
_ <- if(allowedZoneList.contains(zone.name)) isNotApexEndsWithDot(rsForValidations, zone).toResult else ().toResult _ <- if(allowedZoneList.contains(zone.name)) isNotApexEndsWithDot(rsForValidations, zone).toResult else ().toResult
@ -244,16 +246,16 @@ class RecordSetService(
// Check if user is allowed to create dotted hosts using the users present in dotted hosts config // Check if user is allowed to create dotted hosts using the users present in dotted hosts config
def getAllowedDotsLimit(zone: Zone, config: DottedHostsConfig): Int = { def getAllowedDotsLimit(zone: Zone, config: DottedHostsConfig): Int = {
val configZones = config.authConfigs.map(x => x.zone) val configZones = config.zoneAuthConfigs.map(x => x.zone)
val zoneName = if(zone.name.takeRight(1) != ".") zone.name + "." else zone.name val zoneName = if(zone.name.takeRight(1) != ".") zone.name + "." else zone.name
val dottedZoneConfig = configZones.filter(_.contains("*")).map(_.replace("*", "[A-Za-z0-9.]*")) val dottedZoneConfig = configZones.filter(_.contains("*")).map(_.replace("*", "[A-Za-z0-9.]*"))
val isContainWildcardZone = dottedZoneConfig.exists(x => zoneName.matches(x)) val isContainWildcardZone = dottedZoneConfig.exists(x => zoneName.matches(x))
val isContainNormalZone = configZones.contains(zoneName) val isContainNormalZone = configZones.contains(zoneName)
if(isContainNormalZone){ if(isContainNormalZone){
config.authConfigs.filter(x => x.zone == zoneName).head.allowedDotsLimit config.zoneAuthConfigs.filter(x => x.zone == zoneName).head.allowedDotsLimit
} }
else if(isContainWildcardZone){ else if(isContainWildcardZone){
config.authConfigs.filter(x => zoneName.matches(x.zone.replace("*", "[A-Za-z0-9.]*"))).head.allowedDotsLimit config.zoneAuthConfigs.filter(x => zoneName.matches(x.zone.replace("*", "[A-Za-z0-9.]*"))).head.allowedDotsLimit
} }
else { else {
0 0
@ -262,14 +264,14 @@ class RecordSetService(
// Check if user is allowed to create dotted hosts using the users present in dotted hosts config // Check if user is allowed to create dotted hosts using the users present in dotted hosts config
def checkIfInAllowedUsers(zone: Zone, config: DottedHostsConfig, auth: AuthPrincipal): Boolean = { def checkIfInAllowedUsers(zone: Zone, config: DottedHostsConfig, auth: AuthPrincipal): Boolean = {
val configZones = config.authConfigs.map(x => x.zone) val configZones = config.zoneAuthConfigs.map(x => x.zone)
val zoneName = if(zone.name.takeRight(1) != ".") zone.name + "." else zone.name val zoneName = if(zone.name.takeRight(1) != ".") zone.name + "." else zone.name
val dottedZoneConfig = configZones.filter(_.contains("*")).map(_.replace("*", "[A-Za-z0-9.]*")) val dottedZoneConfig = configZones.filter(_.contains("*")).map(_.replace("*", "[A-Za-z0-9.]*"))
val isContainWildcardZone = dottedZoneConfig.exists(x => zoneName.matches(x)) val isContainWildcardZone = dottedZoneConfig.exists(x => zoneName.matches(x))
val isContainNormalZone = configZones.contains(zoneName) val isContainNormalZone = configZones.contains(zoneName)
if(isContainNormalZone){ if(isContainNormalZone){
val users = config.authConfigs.flatMap { val users = config.zoneAuthConfigs.flatMap {
x: AuthConfigs => x: ZoneAuthConfigs =>
if (x.zone == zoneName) x.allowedUserList else List.empty if (x.zone == zoneName) x.allowedUserList else List.empty
} }
if(users.contains(auth.signedInUser.userName)){ if(users.contains(auth.signedInUser.userName)){
@ -280,8 +282,8 @@ class RecordSetService(
} }
} }
else if(isContainWildcardZone){ else if(isContainWildcardZone){
val users = config.authConfigs.flatMap { val users = config.zoneAuthConfigs.flatMap {
x: AuthConfigs => x: ZoneAuthConfigs =>
if (x.zone.contains("*")) { if (x.zone.contains("*")) {
val wildcardZone = x.zone.replace("*", "[A-Za-z0-9.]*") val wildcardZone = x.zone.replace("*", "[A-Za-z0-9.]*")
if (zoneName.matches(wildcardZone)) x.allowedUserList else List.empty if (zoneName.matches(wildcardZone)) x.allowedUserList else List.empty
@ -301,14 +303,14 @@ class RecordSetService(
// Check if user is allowed to create dotted hosts using the record types present in dotted hosts config // Check if user is allowed to create dotted hosts using the record types present in dotted hosts config
def checkIfInAllowedRecordType(zone: Zone, config: DottedHostsConfig, rs: RecordSet): Boolean = { def checkIfInAllowedRecordType(zone: Zone, config: DottedHostsConfig, rs: RecordSet): Boolean = {
val configZones = config.authConfigs.map(x => x.zone) val configZones = config.zoneAuthConfigs.map(x => x.zone)
val zoneName = if(zone.name.takeRight(1) != ".") zone.name + "." else zone.name val zoneName = if(zone.name.takeRight(1) != ".") zone.name + "." else zone.name
val dottedZoneConfig = configZones.filter(_.contains("*")).map(_.replace("*", "[A-Za-z0-9.]*")) val dottedZoneConfig = configZones.filter(_.contains("*")).map(_.replace("*", "[A-Za-z0-9.]*"))
val isContainWildcardZone = dottedZoneConfig.exists(x => zoneName.matches(x)) val isContainWildcardZone = dottedZoneConfig.exists(x => zoneName.matches(x))
val isContainNormalZone = configZones.contains(zoneName) val isContainNormalZone = configZones.contains(zoneName)
if(isContainNormalZone){ if(isContainNormalZone){
val rType = config.authConfigs.flatMap { val rType = config.zoneAuthConfigs.flatMap {
x: AuthConfigs => x: ZoneAuthConfigs =>
if (x.zone == zoneName) x.allowedRecordType else List.empty if (x.zone == zoneName) x.allowedRecordType else List.empty
} }
if(rType.contains(rs.typ.toString)){ if(rType.contains(rs.typ.toString)){
@ -319,8 +321,8 @@ class RecordSetService(
} }
} }
else if(isContainWildcardZone){ else if(isContainWildcardZone){
val rType = config.authConfigs.flatMap { val rType = config.zoneAuthConfigs.flatMap {
x: AuthConfigs => x: ZoneAuthConfigs =>
if (x.zone.contains("*")) { if (x.zone.contains("*")) {
val wildcardZone = x.zone.replace("*", "[A-Za-z0-9.]*") val wildcardZone = x.zone.replace("*", "[A-Za-z0-9.]*")
if (zoneName.matches(wildcardZone)) x.allowedRecordType else List.empty if (zoneName.matches(wildcardZone)) x.allowedRecordType else List.empty
@ -340,20 +342,20 @@ class RecordSetService(
// Check if user is allowed to create dotted hosts using the groups present in dotted hosts config // Check if user is allowed to create dotted hosts using the groups present in dotted hosts config
def checkIfInAllowedGroups(zone: Zone, config: DottedHostsConfig, auth: AuthPrincipal): IO[Boolean] = { def checkIfInAllowedGroups(zone: Zone, config: DottedHostsConfig, auth: AuthPrincipal): IO[Boolean] = {
val configZones = config.authConfigs.map(x => x.zone) val configZones = config.zoneAuthConfigs.map(x => x.zone)
val zoneName = if(zone.name.takeRight(1) != ".") zone.name + "." else zone.name val zoneName = if(zone.name.takeRight(1) != ".") zone.name + "." else zone.name
val dottedZoneConfig = configZones.filter(_.contains("*")).map(_.replace("*", "[A-Za-z0-9.]*")) val dottedZoneConfig = configZones.filter(_.contains("*")).map(_.replace("*", "[A-Za-z0-9.]*"))
val isContainWildcardZone = dottedZoneConfig.exists(x => zoneName.matches(x)) val isContainWildcardZone = dottedZoneConfig.exists(x => zoneName.matches(x))
val isContainNormalZone = configZones.contains(zoneName) val isContainNormalZone = configZones.contains(zoneName)
val groups = if(isContainNormalZone){ val groups = if(isContainNormalZone){
config.authConfigs.flatMap { config.zoneAuthConfigs.flatMap {
x: AuthConfigs => x: ZoneAuthConfigs =>
if (x.zone == zoneName) x.allowedGroupList else List.empty if (x.zone == zoneName) x.allowedGroupList else List.empty
} }
} }
else if(isContainWildcardZone){ else if(isContainWildcardZone){
config.authConfigs.flatMap { config.zoneAuthConfigs.flatMap {
x: AuthConfigs => x: ZoneAuthConfigs =>
if (x.zone.contains("*")) { if (x.zone.contains("*")) {
val wildcardZone = x.zone.replace("*", "[A-Za-z0-9.]*") val wildcardZone = x.zone.replace("*", "[A-Za-z0-9.]*")
if (zoneName.matches(wildcardZone)) x.allowedGroupList else List.empty if (zoneName.matches(wildcardZone)) x.allowedGroupList else List.empty

View File

@ -97,7 +97,8 @@ object RecordSetValidations {
existingRecordSet: Option[RecordSet] = None, existingRecordSet: Option[RecordSet] = None,
recordFqdnDoesNotExist: Boolean, recordFqdnDoesNotExist: Boolean,
dottedHostZoneConfig: Set[String], dottedHostZoneConfig: Set[String],
isRecordTypeAndUserAllowed: Boolean isRecordTypeAndUserAllowed: Boolean,
allowedDotsLimit: Int = 0
): Either[Throwable, Unit] = { ): Either[Throwable, Unit] = {
val zoneName = if(zone.name.takeRight(1) != ".") zone.name + "." else zone.name val zoneName = if(zone.name.takeRight(1) != ".") zone.name + "." else zone.name
@ -105,7 +106,7 @@ object RecordSetValidations {
val isDomainAllowed = dottedHostZoneConfig.contains(zoneName) val isDomainAllowed = dottedHostZoneConfig.contains(zoneName)
// Check if record set contains dot and if it is in zone which is allowed to have dotted records from dotted hosts config // Check if record set contains dot and if it is in zone which is allowed to have dotted records from dotted hosts config
if(newRecordSet.name.contains(".") && isDomainAllowed && newRecordSet.name != zone.name) { if(allowedDotsLimit != 0 && newRecordSet.name.contains(".") && isDomainAllowed && newRecordSet.name != zone.name) {
if(!isRecordTypeAndUserAllowed){ if(!isRecordTypeAndUserAllowed){
isUserAndRecordTypeAuthorized(newRecordSet, zone, existingRecordSet, recordFqdnDoesNotExist, isRecordTypeAndUserAllowed) isUserAndRecordTypeAuthorized(newRecordSet, zone, existingRecordSet, recordFqdnDoesNotExist, isRecordTypeAndUserAllowed)
} }
@ -175,16 +176,17 @@ object RecordSetValidations {
approvedNameServers: List[Regex], approvedNameServers: List[Regex],
recordFqdnDoesNotExist: Boolean, recordFqdnDoesNotExist: Boolean,
dottedHostZoneConfig: Set[String], dottedHostZoneConfig: Set[String],
isRecordTypeAndUserAllowed: Boolean isRecordTypeAndUserAllowed: Boolean,
allowedDotsLimit: Int = 0
): Either[Throwable, Unit] = ): Either[Throwable, Unit] =
newRecordSet.typ match { newRecordSet.typ match {
case CNAME => cnameValidations(newRecordSet, existingRecordsWithName, zone, existingRecordSet, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed) case CNAME => cnameValidations(newRecordSet, existingRecordsWithName, zone, existingRecordSet, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed, allowedDotsLimit)
case NS => nsValidations(newRecordSet, zone, existingRecordSet, approvedNameServers, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed) case NS => nsValidations(newRecordSet, zone, existingRecordSet, approvedNameServers, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed, allowedDotsLimit)
case SOA => soaValidations(newRecordSet, zone, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed) case SOA => soaValidations(newRecordSet, zone, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed, allowedDotsLimit)
case PTR => ptrValidations(newRecordSet, zone) case PTR => ptrValidations(newRecordSet, zone)
case SRV | TXT | NAPTR => ().asRight // SRV, TXT and NAPTR do not go through dotted host check case SRV | TXT | NAPTR => ().asRight // SRV, TXT and NAPTR do not go through dotted host check
case DS => dsValidations(newRecordSet, existingRecordsWithName, zone, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed) case DS => dsValidations(newRecordSet, existingRecordsWithName, zone, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed, allowedDotsLimit)
case _ => checkForDot(newRecordSet, zone, existingRecordSet, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed) case _ => checkForDot(newRecordSet, zone, existingRecordSet, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed, allowedDotsLimit)
} }
def typeSpecificDeleteValidations(recordSet: RecordSet, zone: Zone): Either[Throwable, Unit] = def typeSpecificDeleteValidations(recordSet: RecordSet, zone: Zone): Either[Throwable, Unit] =
@ -208,7 +210,8 @@ object RecordSetValidations {
existingRecordSet: Option[RecordSet] = None, existingRecordSet: Option[RecordSet] = None,
recordFqdnDoesNotExist: Boolean, recordFqdnDoesNotExist: Boolean,
dottedHostZoneConfig: Set[String], dottedHostZoneConfig: Set[String],
isRecordTypeAndUserAllowed: Boolean isRecordTypeAndUserAllowed: Boolean,
allowedDotsLimit: Int = 0
): Either[Throwable, Unit] = { ): Either[Throwable, Unit] = {
// cannot create a cname record if a record with the same exists // cannot create a cname record if a record with the same exists
val noRecordWithName = { val noRecordWithName = {
@ -241,7 +244,7 @@ object RecordSetValidations {
) )
_ <- noRecordWithName _ <- noRecordWithName
_ <- RDataWithConsecutiveDots _ <- RDataWithConsecutiveDots
_ <- checkForDot(newRecordSet, zone, existingRecordSet, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed) _ <- checkForDot(newRecordSet, zone, existingRecordSet, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed, allowedDotsLimit)
} yield () } yield ()
} }
@ -252,7 +255,8 @@ object RecordSetValidations {
zone: Zone, zone: Zone,
recordFqdnDoesNotExist: Boolean, recordFqdnDoesNotExist: Boolean,
dottedHostZoneConfig: Set[String], dottedHostZoneConfig: Set[String],
isRecordTypeAndUserAllowed: Boolean isRecordTypeAndUserAllowed: Boolean,
allowedDotsLimit: Int = 0
): Either[Throwable, Unit] = { ): Either[Throwable, Unit] = {
// see https://tools.ietf.org/html/rfc4035#section-2.4 // see https://tools.ietf.org/html/rfc4035#section-2.4
val nsChecks = existingRecordsWithName.find(_.typ == NS) match { val nsChecks = existingRecordsWithName.find(_.typ == NS) match {
@ -265,7 +269,7 @@ object RecordSetValidations {
} }
for { for {
_ <- checkForDot(newRecordSet, zone, None, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed) _ <- checkForDot(newRecordSet, zone, None, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed, allowedDotsLimit)
_ <- isNotOrigin( _ <- isNotOrigin(
newRecordSet, newRecordSet,
zone, zone,
@ -282,10 +286,11 @@ object RecordSetValidations {
approvedNameServers: List[Regex], approvedNameServers: List[Regex],
recordFqdnDoesNotExist: Boolean, recordFqdnDoesNotExist: Boolean,
dottedHostZoneConfig: Set[String], dottedHostZoneConfig: Set[String],
isRecordTypeAndUserAllowed: Boolean isRecordTypeAndUserAllowed: Boolean,
allowedDotsLimit: Int = 0
): Either[Throwable, Unit] = { ): Either[Throwable, Unit] = {
// TODO kept consistency with old validation. Not sure why NS could be dotted in reverse specifically // TODO kept consistency with old validation. Not sure why NS could be dotted in reverse specifically
val isNotDottedHost = if (!zone.isReverse) checkForDot(newRecordSet, zone, None, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed) else ().asRight val isNotDottedHost = if (!zone.isReverse) checkForDot(newRecordSet, zone, None, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed, allowedDotsLimit) else ().asRight
for { for {
_ <- isNotDottedHost _ <- isNotDottedHost
@ -307,9 +312,9 @@ object RecordSetValidations {
} yield () } yield ()
} }
def soaValidations(newRecordSet: RecordSet, zone: Zone, recordFqdnDoesNotExist: Boolean, dottedHostZoneConfig: Set[String], isRecordTypeAndUserAllowed: Boolean): Either[Throwable, Unit] = def soaValidations(newRecordSet: RecordSet, zone: Zone, recordFqdnDoesNotExist: Boolean, dottedHostZoneConfig: Set[String], isRecordTypeAndUserAllowed: Boolean, allowedDotsLimit: Int = 0): Either[Throwable, Unit] =
// TODO kept consistency with old validation. in theory if SOA always == zone name, no special case is needed here // TODO kept consistency with old validation. in theory if SOA always == zone name, no special case is needed here
if (!zone.isReverse) checkForDot(newRecordSet, zone, None, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed) else ().asRight if (!zone.isReverse) checkForDot(newRecordSet, zone, None, recordFqdnDoesNotExist, dottedHostZoneConfig, isRecordTypeAndUserAllowed, allowedDotsLimit) else ().asRight
def ptrValidations(newRecordSet: RecordSet, zone: Zone): Either[Throwable, Unit] = def ptrValidations(newRecordSet: RecordSet, zone: Zone): Either[Throwable, Unit] =
// TODO we don't check for PTR as dotted...not sure why // TODO we don't check for PTR as dotted...not sure why

View File

@ -18,7 +18,7 @@ package vinyldns.api
import com.comcast.ip4s.IpAddress import com.comcast.ip4s.IpAddress
import org.joda.time.DateTime import org.joda.time.DateTime
import vinyldns.api.config.{AuthConfigs, BatchChangeConfig, DottedHostsConfig, HighValueDomainConfig, LimitsConfig, ManualReviewConfig, ScheduledChangesConfig} import vinyldns.api.config.{ZoneAuthConfigs, BatchChangeConfig, DottedHostsConfig, HighValueDomainConfig, LimitsConfig, ManualReviewConfig, ScheduledChangesConfig}
import vinyldns.api.domain.batch.V6DiscoveryNibbleBoundaries import vinyldns.api.domain.batch.V6DiscoveryNibbleBoundaries
import vinyldns.core.domain.record._ import vinyldns.core.domain.record._
import vinyldns.core.domain.zone._ import vinyldns.core.domain.zone._
@ -40,7 +40,7 @@ trait VinylDNSTestHelpers {
val approvedNameServers: List[Regex] = List(new Regex("some.test.ns.")) val approvedNameServers: List[Regex] = List(new Regex("some.test.ns."))
val dottedHostsConfig: DottedHostsConfig = DottedHostsConfig(List(AuthConfigs("dotted.xyz.",List("xyz"),List("dummy"),List("CNAME"), 3), AuthConfigs("abc.zone.recordsets.",List("locked"),List("dummy"),List("CNAME"), 3), AuthConfigs("xyz.",List("super"),List("xyz"),List("CNAME"), 3))) val dottedHostsConfig: DottedHostsConfig = DottedHostsConfig(List(ZoneAuthConfigs("dotted.xyz.",List("xyz"),List("dummy"),List("CNAME"), 3), ZoneAuthConfigs("abc.zone.recordsets.",List("locked"),List("dummy"),List("CNAME"), 3), ZoneAuthConfigs("xyz.",List("super"),List("xyz"),List("CNAME"), 3), ZoneAuthConfigs("dot.xyz.",List("super"),List("xyz"),List("CNAME"), 0)))
val emptyDottedHostsConfig: DottedHostsConfig = DottedHostsConfig(List.empty) val emptyDottedHostsConfig: DottedHostsConfig = DottedHostsConfig(List.empty)

View File

@ -24,7 +24,7 @@ import org.scalatestplus.mockito.MockitoSugar
import org.scalatest.matchers.should.Matchers import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec import org.scalatest.wordspec.AnyWordSpec
import org.scalatest.BeforeAndAfterEach import org.scalatest.BeforeAndAfterEach
import vinyldns.api.config.{AuthConfigs, DottedHostsConfig} import vinyldns.api.config.{ZoneAuthConfigs, DottedHostsConfig}
import vinyldns.api.{ResultHelpers, VinylDNSTestHelpers} import vinyldns.api.{ResultHelpers, VinylDNSTestHelpers}
import vinyldns.api.domain.access.AccessValidations import vinyldns.api.domain.access.AccessValidations
import vinyldns.api.domain.record.RecordSetHelpers._ import vinyldns.api.domain.record.RecordSetHelpers._
@ -128,14 +128,14 @@ class RecordSetServiceSpec
) )
def getDottedHostsConfigGroupsAllowed(zone: Zone, config: DottedHostsConfig): List[String] = { def getDottedHostsConfigGroupsAllowed(zone: Zone, config: DottedHostsConfig): List[String] = {
val configZones = config.authConfigs.map(x => x.zone) val configZones = config.zoneAuthConfigs.map(x => x.zone)
val zoneName = if(zone.name.takeRight(1) != ".") zone.name + "." else zone.name val zoneName = if(zone.name.takeRight(1) != ".") zone.name + "." else zone.name
val dottedZoneConfig = configZones.filter(_.contains("*")).map(_.replace("*", "[A-Za-z.]*")) val dottedZoneConfig = configZones.filter(_.contains("*")).map(_.replace("*", "[A-Za-z.]*"))
val isContainWildcardZone = dottedZoneConfig.exists(x => zoneName.substring(0, zoneName.length - 1).matches(x)) val isContainWildcardZone = dottedZoneConfig.exists(x => zoneName.substring(0, zoneName.length - 1).matches(x))
val isContainNormalZone = configZones.contains(zoneName) val isContainNormalZone = configZones.contains(zoneName)
val groups = if (isContainWildcardZone || isContainNormalZone) { val groups = if (isContainWildcardZone || isContainNormalZone) {
config.authConfigs.flatMap { config.zoneAuthConfigs.flatMap {
x: AuthConfigs => x: ZoneAuthConfigs =>
if (x.zone.contains("*")) { if (x.zone.contains("*")) {
val wildcardZone = x.zone.replace("*", "[A-Za-z.]*") val wildcardZone = x.zone.replace("*", "[A-Za-z.]*")
if (zoneName.substring(0, zoneName.length - 1).matches(wildcardZone)) x.allowedGroupList else List.empty if (zoneName.substring(0, zoneName.length - 1).matches(wildcardZone)) x.allowedGroupList else List.empty
@ -150,7 +150,7 @@ class RecordSetServiceSpec
groups groups
} }
val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.authConfigs.map(x => x.zone) val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.zoneAuthConfigs.map(x => x.zone)
val dottedHostsConfigGroupsAllowed: List[String] = getDottedHostsConfigGroupsAllowed(okZone, VinylDNSTestHelpers.dottedHostsConfig) val dottedHostsConfigGroupsAllowed: List[String] = getDottedHostsConfigGroupsAllowed(okZone, VinylDNSTestHelpers.dottedHostsConfig)
@ -164,7 +164,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(okZone.id, record.name) .getRecordSetsByName(okZone.id, record.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -234,7 +234,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(okZone.id, record.name) .getRecordSetsByName(okZone.id, record.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -304,7 +304,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(okZone.id, record.name) .getRecordSetsByName(okZone.id, record.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -350,7 +350,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(okZone.id, record.name) .getRecordSetsByName(okZone.id, record.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -389,7 +389,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(okZone.id, record.name) .getRecordSetsByName(okZone.id, record.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -447,7 +447,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(Some(okGroup))) doReturn(IO.pure(Some(okGroup)))
.when(mockGroupRepo) .when(mockGroupRepo)
.getGroup(okGroup.id) .getGroup(okGroup.id)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -521,7 +521,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(okZone.id, record.name) .getRecordSetsByName(okZone.id, record.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -560,7 +560,7 @@ class RecordSetServiceSpec
val record = val record =
cname.copy(name = "new.name", zoneId = dottedZone.id, status = RecordSetStatus.Active) cname.copy(name = "new.name", zoneId = dottedZone.id, status = RecordSetStatus.Active)
val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.authConfigs.map(x => x.zone) val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.zoneAuthConfigs.map(x => x.zone)
val dottedHostsConfigGroupsAllowed: List[String] = getDottedHostsConfigGroupsAllowed(dottedZone, VinylDNSTestHelpers.dottedHostsConfig) val dottedHostsConfigGroupsAllowed: List[String] = getDottedHostsConfigGroupsAllowed(dottedZone, VinylDNSTestHelpers.dottedHostsConfig)
@ -571,7 +571,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(dottedZone.id, record.name) .getRecordSetsByName(dottedZone.id, record.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -604,7 +604,7 @@ class RecordSetServiceSpec
val record = val record =
cname.copy(name = "new.name", zoneId = xyzZone.id, status = RecordSetStatus.Active) cname.copy(name = "new.name", zoneId = xyzZone.id, status = RecordSetStatus.Active)
val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.authConfigs.map(x => x.zone) val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.zoneAuthConfigs.map(x => x.zone)
val dottedHostsConfigGroupsAllowed: List[String] = getDottedHostsConfigGroupsAllowed(xyzZone, VinylDNSTestHelpers.dottedHostsConfig) val dottedHostsConfigGroupsAllowed: List[String] = getDottedHostsConfigGroupsAllowed(xyzZone, VinylDNSTestHelpers.dottedHostsConfig)
@ -644,6 +644,47 @@ class RecordSetServiceSpec
result.recordSet.name shouldBe record.name result.recordSet.name shouldBe record.name
} }
"fail if the record is dotted and zone, user, record type is allowed but number of dots allowed in config is 0" in {
val record =
cname.copy(name = "new.name", zoneId = dotZone.id, status = RecordSetStatus.Active)
val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.zoneAuthConfigs.map(x => x.zone)
val dottedHostsConfigGroupsAllowed: List[String] = getDottedHostsConfigGroupsAllowed(dottedZone, VinylDNSTestHelpers.dottedHostsConfig)
doReturn(IO.pure(Some(dotZone))).when(mockZoneRepo).getZone(dotZone.id)
doReturn(IO.pure(List()))
.when(mockRecordRepo)
.getRecordSets(dotZone.id, record.name, record.typ)
doReturn(IO.pure(List()))
.when(mockRecordRepo)
.getRecordSetsByName(dotZone.id, record.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set()))
.when(mockZoneRepo)
.getZonesByFilters(Set.empty)
doReturn(IO.pure(None))
.when(mockZoneRepo)
.getZoneByName(record.name + "." + dotZone.name)
doReturn(IO.pure(List()))
.when(mockRecordRepo)
.getRecordSetsByFQDNs(Set(record.name + "." + dotZone.name))
doReturn(IO.pure(Set()))
.when(mockZoneRepo)
.getZonesByFilters(record.name.split('.').map(x => x + "." + dotZone.name).toSet)
doReturn(IO.pure(Set(dummyGroup)))
.when(mockGroupRepo)
.getGroupsByName(dottedHostsConfigGroupsAllowed.toSet)
doReturn(IO.pure(ListUsersResults(listOfDummyUsers.toSeq, None)))
.when(mockUserRepo)
.getUsers(dummyGroup.memberIds, None, None)
// fails as no.of.dots allowed for the zone in the config is 0
val result = leftResultOf(underTest.addRecordSet(record, xyzAuth).value)
result shouldBe an[InvalidRequest]
}
"fail if the record is dotted and user, record type is in allowed dotted hosts config except zone" in { "fail if the record is dotted and user, record type is in allowed dotted hosts config except zone" in {
val record = val record =
cname.copy(name = "new.name", zoneId = okZone.id, status = RecordSetStatus.Active) cname.copy(name = "new.name", zoneId = okZone.id, status = RecordSetStatus.Active)
@ -654,7 +695,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(okZone.id, record.name) .getRecordSetsByName(okZone.id, record.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -684,7 +725,7 @@ class RecordSetServiceSpec
val record = val record =
cname.copy(name = "new.name", zoneId = abcZone.id, status = RecordSetStatus.Active) cname.copy(name = "new.name", zoneId = abcZone.id, status = RecordSetStatus.Active)
val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.authConfigs.map(x => x.zone) val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.zoneAuthConfigs.map(x => x.zone)
val dottedHostsConfigGroupsAllowed: List[String] = getDottedHostsConfigGroupsAllowed(abcZone, VinylDNSTestHelpers.dottedHostsConfig) val dottedHostsConfigGroupsAllowed: List[String] = getDottedHostsConfigGroupsAllowed(abcZone, VinylDNSTestHelpers.dottedHostsConfig)
@ -725,8 +766,8 @@ class RecordSetServiceSpec
val record = val record =
aaaa.copy(name = "new.name", zoneId = dottedZone.id, status = RecordSetStatus.Active) aaaa.copy(name = "new.name", zoneId = dottedZone.id, status = RecordSetStatus.Active)
val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.authConfigs.map { val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.zoneAuthConfigs.map {
case y:AuthConfigs => y.zone case y:ZoneAuthConfigs => y.zone
} }
val dottedHostsConfigGroupsAllowed: List[String] = getDottedHostsConfigGroupsAllowed(dottedZone, VinylDNSTestHelpers.dottedHostsConfig) val dottedHostsConfigGroupsAllowed: List[String] = getDottedHostsConfigGroupsAllowed(dottedZone, VinylDNSTestHelpers.dottedHostsConfig)
@ -738,7 +779,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(dottedZone.id, record.name) .getRecordSetsByName(dottedZone.id, record.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -779,7 +820,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(okZone.id, newRecord.name) .getRecordSetsByName(okZone.id, newRecord.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -836,7 +877,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(okZone.id, newRecord.name) .getRecordSetsByName(okZone.id, newRecord.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -896,7 +937,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(okZone.id, newRecord.name) .getRecordSetsByName(okZone.id, newRecord.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -939,7 +980,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(okZone.id, newRecord.name) .getRecordSetsByName(okZone.id, newRecord.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -982,7 +1023,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(List())) doReturn(IO.pure(List()))
.when(mockRecordRepo) .when(mockRecordRepo)
.getRecordSetsByName(okZone.id, newRecord.name) .getRecordSetsByName(okZone.id, newRecord.name)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))
@ -1138,7 +1179,7 @@ class RecordSetServiceSpec
doReturn(IO.pure(Some(oneUserDummyGroup))) doReturn(IO.pure(Some(oneUserDummyGroup)))
.when(mockGroupRepo) .when(mockGroupRepo)
.getGroup(oneUserDummyGroup.id) .getGroup(oneUserDummyGroup.id)
doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone))) doReturn(IO.pure(Set(dottedZone, abcZone, xyzZone, dotZone)))
.when(mockZoneRepo) .when(mockZoneRepo)
.getZonesByNames(dottedHostsConfigZonesAllowed.toSet) .getZonesByNames(dottedHostsConfigZonesAllowed.toSet)
doReturn(IO.pure(Set())) doReturn(IO.pure(Set()))

View File

@ -44,7 +44,7 @@ class RecordSetValidationsSpec
import RecordSetValidations._ import RecordSetValidations._
val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.authConfigs.map(x => x.zone) val dottedHostsConfigZonesAllowed: List[String] = VinylDNSTestHelpers.dottedHostsConfig.zoneAuthConfigs.map(x => x.zone)
"RecordSetValidations" should { "RecordSetValidations" should {
"validRecordTypes" should { "validRecordTypes" should {
@ -232,18 +232,30 @@ class RecordSetValidationsSpec
} }
"return a success for any new record with dotted hosts in forward zones if it satisfies dotted hosts configs" in { "return a success for any new record with dotted hosts in forward zones if it satisfies dotted hosts configs" in {
val record = typeSpecificValidations(dottedARecord.copy(zoneId = dottedZone.id), List(), dottedZone, None, Nil, true, dottedHostsConfigZonesAllowed.toSet, true) // Zone, User, Record Type and Number of dots are all satisfied
val record = typeSpecificValidations(dottedARecord.copy(typ = CNAME, zoneId = dottedZone.id), List(), dottedZone, None, Nil, true, dottedHostsConfigZonesAllowed.toSet, true, 5)
record should be(right) record should be(right)
} }
"return a failure for any new record with dotted hosts in forward zones (CNAME) if it satisfies dotted hosts configs" in { "return a failure for any new record with dotted hosts if no.of.dots allowed is 0" in {
val record = typeSpecificValidations(dottedARecord.copy(typ = CNAME, zoneId = dottedZone.id), List(), dottedZone, None, Nil, true, dottedHostsConfigZonesAllowed.toSet, true) // Zone, User, Record Type and Number of dots are all satisfied
record should be(right) leftValue(
typeSpecificValidations(dottedARecord.copy(typ = CNAME, zoneId = dottedZone.id), List(), dottedZone, None, Nil, true, dottedHostsConfigZonesAllowed.toSet, true, 0)
) shouldBe an[InvalidRequest]
} }
"return a failure for any new record with dotted hosts in forward zones (NS) if it satisfies dotted hosts configs" in { "return a failure for any new record with dotted hosts in forward zones (A record) if it doesn't satisfy dotted hosts configs" in {
val record = typeSpecificValidations(dottedARecord.copy(typ = NS, zoneId = dottedZone.id), List(), dottedZone, None, Nil, true, dottedHostsConfigZonesAllowed.toSet, true) // 'A' record is not allowed in the config
record should be(right) leftValue(
typeSpecificValidations(dottedARecord.copy(zoneId = dottedZone.id), List(), dottedZone, None, Nil, true, dottedHostsConfigZonesAllowed.toSet, false, 5)
) shouldBe an[InvalidRequest]
}
"return a failure for any new record with dotted hosts in forward zones (NS record) if it doesn't satisfy dotted hosts configs" in {
// 'NS' record is not allowed in the config
leftValue(
typeSpecificValidations(dottedARecord.copy(typ = NS, zoneId = dottedZone.id), List(), dottedZone, None, Nil, true, dottedHostsConfigZonesAllowed.toSet, false, 5)
) shouldBe an[InvalidRequest]
} }
"return a success for any existing record with dotted hosts in forward zones" in { "return a success for any existing record with dotted hosts in forward zones" in {
@ -445,7 +457,7 @@ class RecordSetValidationsSpec
} }
"return ok if the DS is dotted and zone, user, record type is allowed in dotted hosts config" in { "return ok if the DS is dotted and zone, user, record type is allowed in dotted hosts config" in {
val record = val record =
dsValidations(ds.copy(name = "dotted.trial", zoneId = dottedZone.id), List(matchingNs), dottedZone, true, dottedHostsConfigZonesAllowed.toSet, true) dsValidations(ds.copy(name = "dotted.trial", zoneId = dottedZone.id), List(matchingNs), dottedZone, true, dottedHostsConfigZonesAllowed.toSet, true, 5)
record should be(right) record should be(right)
} }
"return an InvalidRequest if the DS is dotted and zone, user, record type is allowed in dotted hosts config but has a conflict with existing record or zone" in { "return an InvalidRequest if the DS is dotted and zone, user, record type is allowed in dotted hosts config but has a conflict with existing record or zone" in {
@ -508,7 +520,7 @@ class RecordSetValidationsSpec
} }
"return ok if the CNAME is dotted and zone, user, record type is allowed in dotted hosts config" in { "return ok if the CNAME is dotted and zone, user, record type is allowed in dotted hosts config" in {
val record = val record =
cnameValidations(cname.copy(name = "dot.ted", zoneId = dottedZone.id), List(), dottedZone, None, true, dottedHostsConfigZonesAllowed.toSet, true) cnameValidations(cname.copy(name = "dot.ted", zoneId = dottedZone.id), List(), dottedZone, None, true, dottedHostsConfigZonesAllowed.toSet, true, 5)
record should be(right) record should be(right)
} }
"return an InvalidRequest if the CNAME is dotted and zone, user, record type is allowed in dotted hosts config but has a conflict with existing record or zone" in { "return an InvalidRequest if the CNAME is dotted and zone, user, record type is allowed in dotted hosts config but has a conflict with existing record or zone" in {

View File

@ -35,6 +35,7 @@ object TestZoneData {
connection = testConnection connection = testConnection
) )
val dottedZone: Zone = Zone("dotted.xyz.", "dotted@xyz.com", adminGroupId = xyzGroup.id) val dottedZone: Zone = Zone("dotted.xyz.", "dotted@xyz.com", adminGroupId = xyzGroup.id)
val dotZone: Zone = Zone("dot.xyz.", "dotted@xyz.com", adminGroupId = xyzGroup.id)
val abcZone: Zone = Zone("abc.zone.recordsets.", "test@test.com", adminGroupId = abcGroup.id) val abcZone: Zone = Zone("abc.zone.recordsets.", "test@test.com", adminGroupId = abcGroup.id)
val xyzZone: Zone = Zone("xyz.", "abc@xyz.com", adminGroupId = xyzGroup.id) val xyzZone: Zone = Zone("xyz.", "abc@xyz.com", adminGroupId = xyzGroup.id)
val zoneIp4: Zone = Zone("0.162.198.in-addr.arpa.", "test@test.com", adminGroupId = abcGroup.id) val zoneIp4: Zone = Zone("0.162.198.in-addr.arpa.", "test@test.com", adminGroupId = abcGroup.id)