Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BE: RBAC: Impl Active Directory populator #717

Merged
merged 8 commits into from
Dec 31, 2024
Merged

BE: RBAC: Impl Active Directory populator #717

merged 8 commits into from
Dec 31, 2024

Conversation

Haarolean
Copy link
Member

@Haarolean Haarolean commented Dec 16, 2024

  • Breaking change? (if so, please describe the impact and migration path for existing application instances)

What changes did you make? (Give an overview)

Is there anything you'd like reviewers to focus on?

How Has This Been Tested? (put an "x" (case-sensitive!) next to an item)

  • No need to
  • Manually (please, describe, if necessary)
  • Unit checks
  • Integration checks
  • Covered by existing automation

Checklist (put an "x" (case-sensitive!) next to all the items, otherwise the build will fail)

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (e.g. ENVIRONMENT VARIABLES)
  • My changes generate no new warnings (e.g. Sonar is happy)
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged

Check out Contributing and Code of Conduct

A picture of a cute animal (not mandatory but encouraged)

@Haarolean Haarolean self-assigned this Dec 16, 2024
@Haarolean Haarolean requested a review from a team as a code owner December 16, 2024 14:41
@kapybro kapybro bot added status/triage Issues pending maintainers triage area/rbac Related to Role Based Access Control feature status/triage/completed Automatic triage completed and removed status/triage Issues pending maintainers triage labels Dec 16, 2024
@Haarolean Haarolean added scope/backend Related to backend changes type/chore Boring stuff, could be refactoring or tech debt type/refactor Refactoring task and removed type/chore Boring stuff, could be refactoring or tech debt labels Dec 16, 2024
@Haarolean
Copy link
Member Author

@wernerdv wanna take a look?

@wernerdv
Copy link
Contributor

@Haarolean Yes, I'll check locally with these changes and report back.

@wernerdv
Copy link
Contributor

wernerdv commented Dec 16, 2024

@Haarolean A few comments:

1 - https://github.com/kafbat/kafka-ui/pull/717/files#diff-af0ab81f6ae459e9fd60e1979d12b70ab8556054fe012848b0e930ade92208a5R52 need @Autowired(required = false) LdapAuthoritiesPopulator authoritiesExtractor.
Otherwise there will be an error on startup.

2 - we can make LdapSecurityConfig extends AbstractAuthSecurityConfig and remove static import for AUTH_WHITELIST.

3 - But most importantly, RBAC with AD still only works correctly if rbac.roles.name is group from AD.
https://github.com/kafbat/kafka-ui/blob/main/api/src/main/java/io/kafbat/ui/controller/AccessController.java#L37
https://github.com/kafbat/kafka-ui/blob/main/api/src/main/java/io/kafbat/ui/service/rbac/AccessControlService.java#L204

If not, then /api/authorization returns empty permissions for user.

When I did that and checked locally - RBAC is working as expected with any parameter value rbac.roles.name (not just when it's an AD group):

private Predicate<Role> filterRole(AuthenticatedUser user) {
  return role -> true;
}

@Haarolean Haarolean changed the title BE: Chore: RBAC: LDAP security config refactoring BE: RBAC: Impl Active Directory populator Dec 26, 2024
@Haarolean Haarolean added the type/enhancement En enhancement/improvement to an already existing feature label Dec 26, 2024
@Haarolean
Copy link
Member Author

@wernerdv hey, I've implemented the changes I've talked about here: #717 (comment)
Additionally, did some config refactoring and fixed the stuff you suggested, PTAL again if you're interested

@wernerdv
Copy link
Contributor

wernerdv commented Dec 27, 2024

A couple of fixes:

Otherwise there will be an error on startup.

My yaml config:

kafka:
  update-metrics-rate-millis: 30000 
  clusters:
    - name: LOCAL
      bootstrapServers: localhost:9092
      metrics:
        port: 7010
        type: JMX
        username: admin
        password: qwe123

auth:
  type: LDAP
spring:
  jmx:
    enabled: true
  ldap:
    urls: ldap://host:389
oauth2:
  ldap:
    activeDirectory: true
    activeDirectory.domain: <domain>

rbac:
  roles:
    - name: "my-role"
      clusters:
        - LOCAL
      subjects:
        - provider: ldap_ad
          type: group
          value: my-ad-group
      permissions:
        - resource: applicationconfig
          actions: all
        - resource: clusterconfig
          actions: all

Error at UI startup:

ERROR [main] o.s.b.SpringApplication: Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.reactive.ServerHttpSecurityConfiguration': Unsatisfied dependency expressed through method 'setAuthenticationManager' parameter 0: Error creating bean with name 'authenticationManager' defined in class path resource [io/kafbat/ui/config/auth/LdapSecurityConfig.class]: Unsatisfied dependency expressed through method 'authenticationManager' parameter 0: Error creating bean with name 'authenticationProvider' defined in class path resource [io/kafbat/ui/config/auth/LdapSecurityConfig.class]: Unsatisfied dependency expressed through method 'authenticationProvider' parameter 1: Error creating bean with name 'ldapBindAuthentication' defined in class path resource [io/kafbat/ui/config/auth/LdapSecurityConfig.class]: Either an LdapUserSearch or DN pattern (or both) must be supplied.
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:896)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:849)
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:509)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1439)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625)
        at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
        at io.kafbat.ui.KafkaUiApplication.startApplication(KafkaUiApplication.java:24)
        at io.kafbat.ui.KafkaUiApplication.main(KafkaUiApplication.java:17)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
        at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:102)
        at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:64)
        at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:40)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'authenticationManager' defined in class path resource [io/kafbat/ui/config/auth/LdapSecurityConfig.class]: Unsatisfied dependency expressed through method 'authenticationManager' parameter 0: Error creating bean with name 'authenticationProvider' defined in class path resource [io/kafbat/ui/config/auth/LdapSecurityConfig.class]: Unsatisfied dependency expressed through method 'authenticationProvider' parameter 1: Error creating bean with name 'ldapBindAuthentication' defined in class path resource [io/kafbat/ui/config/auth/LdapSecurityConfig.class]: Either an LdapUserSearch or DN pattern (or both) must be supplied.
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:888)
        ... 24 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'authenticationProvider' defined in class path resource [io/kafbat/ui/config/auth/LdapSecurityConfig.class]: Unsatisfied dependency expressed through method 'authenticationProvider' parameter 1: Error creating bean with name 'ldapBindAuthentication' defined in class path resource [io/kafbat/ui/config/auth/LdapSecurityConfig.class]: Either an LdapUserSearch or DN pattern (or both) must be supplied.
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353)
        at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904)
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782)
        ... 37 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ldapBindAuthentication' defined in class path resource [io/kafbat/ui/config/auth/LdapSecurityConfig.class]: Either an LdapUserSearch or DN pattern (or both) must be supplied.
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1806)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353)
        at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904)
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782)
        ... 51 common frames omitted
Caused by: java.lang.IllegalArgumentException: Either an LdapUserSearch or DN pattern (or both) must be supplied.
        at org.springframework.util.Assert.isTrue(Assert.java:111)
        at org.springframework.security.ldap.authentication.AbstractLdapAuthenticator.afterPropertiesSet(AbstractLdapAuthenticator.java:71)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802)
        ... 62 common frames omitted

@Haarolean
Copy link
Member Author

Otherwise there will be an error on startup.

@wernerdv thanks, fixed!

@Haarolean Haarolean requested a review from wernerdv December 30, 2024 14:17
Copy link
Contributor

@wernerdv wernerdv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked and everything works as expected
LGTM

@Haarolean
Copy link
Member Author

@wernerdv thanks for the review and trying out the changes!

@Haarolean Haarolean merged commit 9f79a56 into main Dec 31, 2024
13 of 15 checks passed
@Haarolean Haarolean deleted the chore/rbac_ad branch December 31, 2024 04:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/rbac Related to Role Based Access Control feature scope/backend Related to backend changes status/triage/completed Automatic triage completed type/enhancement En enhancement/improvement to an already existing feature type/refactor Refactoring task
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BE: RBAC: LDAP: Implement user subject type for LDAP & AD RBAC: Support Active Directory
2 participants