All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.infobip.kafkistry.sql.sources.AclRulesDataSource.kt Maven / Gradle / Ivy

There is a newer version: 0.8.0
Show newest version
@file:Suppress("JpaDataSourceORMInspection")

package com.infobip.kafkistry.sql.sources

import com.infobip.kafkistry.kafka.KafkaAclRule
import com.infobip.kafkistry.model.*
import com.infobip.kafkistry.service.acl.AclsInspectionService
import com.infobip.kafkistry.service.cluster.ClustersRegistryService
import com.infobip.kafkistry.sql.SqlDataSource
import com.infobip.kafkistry.service.acl.AclInspectionResultType
import com.infobip.kafkistry.service.acl.PrincipalAclsInspection
import com.infobip.kafkistry.service.acl.toKafkaAclRule
import org.springframework.stereotype.Component
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicLong
import jakarta.persistence.*

@Component
class AclRulesDataSource(
    private val aclsInspectionService: AclsInspectionService,
    private val clustersRegistry: ClustersRegistryService,
) : SqlDataSource {

    override fun modelAnnotatedClass(): Class = Acl::class.java

    override fun supplyEntities(): List {
        val allClusterRefs = clustersRegistry.listClustersRefs()
        val allPrincipals = aclsInspectionService.inspectAllPrincipals()
        val unknownPrincipals = aclsInspectionService.inspectUnknownPrincipals()
        val aclIdGenerator = AclIdGenerator()
        return (allPrincipals + unknownPrincipals).flatMap {
            mapPrincipalClusterAcls(it, allClusterRefs, aclIdGenerator)
        }
    }

    private class AclIdGenerator {

        private val nextId = AtomicLong(1)
        private val rules = ConcurrentHashMap, Long>()

        fun idFor(clusterIdentifier: KafkaClusterIdentifier, rule: KafkaAclRule): Long {
            return rules.computeIfAbsent(clusterIdentifier to rule) { nextId.getAndIncrement() }
        }
    }

    private fun mapPrincipalClusterAcls(
        principalAclsInspection: PrincipalAclsInspection,
        allClusters: List,
        idGenerator: AclIdGenerator
    ): List {
        val shouldExistMap = principalAclsInspection.principalAcls?.rules?.let { rules ->
            rules.associate { aclRule ->
                val rule = aclRule.toKafkaAclRule(principalAclsInspection.principal)
                rule to allClusters.associate { it.identifier to aclRule.presence.needToBeOnCluster(it) }
            }
        }
        return principalAclsInspection.clusterInspections.flatMap { clusterInspection ->
            clusterInspection.statuses.map { aclRuleStatus ->
                Acl().apply {
                    id = idGenerator.idFor(clusterInspection.clusterIdentifier, aclRuleStatus.rule)
                    principal = principalAclsInspection.principal
                    cluster = clusterInspection.clusterIdentifier
                    acl = aclRuleStatus.rule.toAcl()
                    ok = aclRuleStatus.statusTypes.all { it.valid }
                    status = aclRuleStatus.statusTypes.joinToString(separator = ",") { it.name }
                    exist = aclRuleStatus.statusTypes.mapNotNull { type ->
                        when (type) {
                            AclInspectionResultType.OK, AclInspectionResultType.UNEXPECTED, AclInspectionResultType.UNKNOWN -> true
                            AclInspectionResultType.MISSING, AclInspectionResultType.NOT_PRESENT_AS_EXPECTED, AclInspectionResultType.SECURITY_DISABLED, AclInspectionResultType.UNAVAILABLE -> false
                            AclInspectionResultType.CLUSTER_DISABLED, AclInspectionResultType.CLUSTER_UNREACHABLE -> null
                            else -> null
                        }
                    }.all { it }
                    shouldExist = shouldExistMap
                        ?.get(aclRuleStatus.rule)
                        ?.get(clusterInspection.clusterIdentifier)
                        ?: false
                    affectedTopics = aclRuleStatus.affectedTopics
                    affectedGroups = aclRuleStatus.affectedConsumerGroups
                    conflictingRules = aclRuleStatus.conflictingAcls.map {
                        idGenerator.idFor(clusterInspection.clusterIdentifier, it)
                    }
                }
            }
        }
    }

    private fun KafkaAclRule.toAcl() = AclRule().apply {
        host = [email protected]
        resourceType = resource.type
        resourceName = resource.name
        resourcePattern = resource.namePattern
        operation = [email protected]
        policy = [email protected]
    }

}

@Entity
@Table(name = "Acls")
class Acl {

    @Id
    var id: Long? = null

    lateinit var principal: PrincipalId
    lateinit var cluster: KafkaClusterIdentifier
    lateinit var acl: AclRule

    var ok: Boolean? = null
    lateinit var status: String

    var exist: Boolean? = null
    var shouldExist: Boolean? = null

    @ElementCollection
    @JoinTable(name = "Acls_AffectedTopics")
    @Column(name = "topic")
    lateinit var affectedTopics: List

    @ElementCollection
    @Column(name = "groupId")
    @JoinTable(name = "Acls_AffectedGroups")
    lateinit var affectedGroups: List

    @ElementCollection
    @Column(name = "Acl_otherId")
    @JoinTable(name = "Acls_ConflictingRules")
    lateinit var conflictingRules: List
}

@Embeddable
class AclRule {

    lateinit var host: String

    @Enumerated(EnumType.STRING)
    lateinit var resourceType: AclResource.Type
    lateinit var resourceName: String

    @Enumerated(EnumType.STRING)
    lateinit var resourcePattern: AclResource.NamePattern

    @Enumerated(EnumType.STRING)
    lateinit var operation: AclOperation.Type

    @Enumerated(EnumType.STRING)
    lateinit var policy: AclOperation.Policy

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy