[CloudBees CI 2.277.1.2] Replace Acegi Security with Spring Security & upgrade Spring Framework

Article ID:360057486272
8 minute readKnowledge base

Introduction

The CloudBees CI release 2.277.1.2 replaces the old Acegi Security with Spring Security as part of JEP-227: Replace Acegi Security with Spring Security & upgrade Spring Framework, which is incorporated in Jenkins core since version 2.266.

This replacement might break the normal operation of your Controller especially in tasks related to authorization and the authentication.

This KB article intends to provide guidance so that the upgrade process from a version minor than 2.277.1.2 happens as smoothly as possible.

Motivation

Many security-conscious organizations using, or planning to use, Jenkins will run off-the-shelf security scanners to look for known vulnerabilities. These will commonly flag the extremely old Acegi Security and Spring Core libraries as susceptible and recommend upgrading. While the Jenkins CERT team does not believe that any of these issues are actually exploitable in Jenkins, it is time-consuming for the CERT team to respond to purported security reports, and for users to justify exemptions from policy to use Jenkins anyway.

Expected symptoms of regressions

Most, though not all, affected plugins are those that define a SecurityRealm (authentication plugins such as Active Directory, LDAP or Reverse Proxy Plugin). In case you use a plugin in Jenkins implementing your own custom Security Realm, it is very probable that it will stop working.

The main symptoms are Jenkins not being able to start, or login to fail after upgrade. In case the problem is encountered, you may see ClassNotFoundException and NoSuchMethodError in Jenkins logs such as java.lang.ClassNotFoundException: org.acegisecurity.ldap.LdapDataAccessException.

  • The LDAP and Reverse Proxy Authentication plugins might make Jenkins fail to start with the stack trace below shown in the GUI:

java.lang.IllegalStateException: An attempt to save the global configuration was made before it was loaded
	at jenkins.model.Jenkins.save(Jenkins.java:3381)
	at jenkins.model.Jenkins.saveQuietly(Jenkins.java:3400)
	at jenkins.model.Jenkins.setSecurityRealm(Jenkins.java:2639)
	at jenkins.model.Jenkins$16.run(Jenkins.java:3344)
	at org.jvnet.hudson.reactor.TaskGraphBuilder$TaskImpl.run(TaskGraphBuilder.java:169)
	at org.jvnet.hudson.reactor.Reactor.runTask(Reactor.java:296)
	at jenkins.model.Jenkins$5.runTask(Jenkins.java:1131)
	at org.jvnet.hudson.reactor.Reactor$2.run(Reactor.java:214)
	at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
	at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:68)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused: org.jvnet.hudson.reactor.ReactorException
	at org.jvnet.hudson.reactor.Reactor.execute(Reactor.java:282)
	at jenkins.InitReactorRunner.run(InitReactorRunner.java:49)
	at jenkins.model.Jenkins.executeReactor(Jenkins.java:1164)
	at jenkins.model.Jenkins.<init>(Jenkins.java:962)
	at hudson.model.Hudson.<init>(Hudson.java:85)
	at hudson.model.Hudson.<init>(Hudson.java:81)
	at hudson.WebAppMain$3.run(WebAppMain.java:295)
Caused: hudson.util.HudsonFailedToLoad
	at hudson.WebAppMain$3.run(WebAppMain.java:312)
  • Regarding the Active Directory plugin, Jenkins will correctly start, but the startup logs will show a stacktrace similar to the one below. When trying to log in, a HTTP ERROR 403 No valid crumb was included in the request might be exposed in the GUI.

HTTP ERROR 403 No valid crumb was included in the request
URI:	/j_spring_security_check
STATUS:	403
MESSAGE:	No valid crumb was included in the request
SERVLET:	Stapler

Resolution

The plugin compatibility matrix specifies the status for each plugin regarding this change.

As a general rule, to avoid any issues related to this change, and any other problem in the March release, it is suggested to:

  1. Make sure Beekeeper is configured to upgrade CAP plugins. For this, ensure that the option Manage Jenkins » Beekeeper Upgrade Assistant » CAP Configuration » Allow automatic upgrades of plugins on restart is enabled

  2. Upgrade all the plugins listed under Manage Jenkins » Manage Plugins (Updates tab) except for the cas-plugin.


NOTE

The cas-plugin must be upgraded at the same time as the instance. This means that once the service is stopped, you will need to download the plugin and manually replace $JENKINS_HOME/plugins/cas-plugin.jpi. For further assistance, please, open a support ticket.


In case you would like to get the full picture about the possible impact of this change on your controller, you can execute the Groovy script of the Appendix A under Manage Jenkins » Script Security, which will tell you how you might be affected by this change given the current installed plugins.

Appendix A. Health check Groovy script

def plugins = [
      [name: 'active-directory', version: '2.17', status: 'compatible'],
      [name: 'atlassian-bitbucket-server-integration', version: '2.1.0', status: 'compatible'],
      [name: 'artifactory', version: '3.9.0', status: 'compatible'],
      [name: 'assembla-auth', version: '', status: 'unknown'],
      [name: 'authorize-project', version: '1.3.0', status: 'unknown'],
      [name: 'aws-codecommit-trigger', version: '', status: 'mostly compatible'],
      [name: 'azure-ad', version: '1.2.0', status: 'compatible'],
      [name: 'backlog', version: '', status: 'unknown'],
      [name: 'bitbucket-oauth', version: '0.10', status: 'compatible'],
      [name: 'blueocean', version: '1.24.1', status: 'compatible'],
      [name: 'branch-api', version: '2.6.0', status: 'compatible'],
      [name: 'cas-plugin', version: '1.5.0', status: 'warning'],
      [name: 'cloudbees-bitbucket-branch-source', version: '2.9.3', status: 'compatible'],
      [name: 'cloudbees-folder', version: '', status: 'compatible'],
      [name: 'cloudbees-folder', version: '', status: 'compatible'],
      [name: 'coding-webhook', version: '', status: 'unknown'],
      [name: 'copyartifact', version: '', status: 'compatible'],
      [name: 'credentials', version: '2.3.13', status: 'compatible'],
      [name: 'crowd', version: '', status: 'incompatible'],
      [name: 'crowd2', version: '2.0.2', status: 'compatible'],
      [name: 'declarative-pipeline-migration-assistant', version: '1.1.2', status: 'compatible'],
      [name: 'dry-run', version: '', status: 'mostly compatible'],
      [name: 'extensible-choice-parameter', version: '', status: 'compatible'],
      [name: 'github-oauth', version: '', status: 'probably compatible'],
      [name: 'gitlab-oauth', version: '', status: 'mostly compatible'],
      [name: 'google-cloud-health-check', version: '', status: 'probably compatible'],
      [name: 'google-login', version: '1.6', status: 'compatible'],
      [name: 'jobConfigHistory', version: '', status: 'probably compatible'],
      [name: 'jobtemplates', version: '', status: 'mostly compatible'],
      [name: 'job-dsl', version: '1.77', status: 'compatible'],
      [name: 'junit', version: '1.34', status: 'compatible'],
      [name: 'kerberos-sso', version: '', status: 'probably compatible'],
      [name: 'keycloak', version: '2.3.0', status: 'compatible'],
      [name: 'ldap', version: '1.26', status: 'compatible'],
      [name: 'mac', version: '1.2.1', status: 'mostly compatible'],
      [name: 'matrix-auth', version: '2.6.3', status: 'compatible'],
      [name: 'mock-security-realm', version: '', status: 'compatible'],
      [name: 'nodejs', version: '1.3.8', status: 'compatible'],
      [name: 'oic-auth', version: '1.8', status: 'compatible'],
      [name: 'openid', version: '', status: 'probably compatible'],
      [name: 'openstack-cloud', version: '', status: 'probably compatible'],
      [name: 'ownership', version: '', status: 'mostly compatible'],
      [name: 'pam-auth', version: '', status: 'compatible'],
      [name: 'parameterized-trigger', version: '2.38', status: 'compatible'],
      [name: 'pipeline-maven', version: '3.9.3', status: 'compatible'],
      [name: 'pipeline-restful-api', version: '0.10', status: 'compatible'],
      [name: 'plugin-util-api', version: '1.2.5', status: 'compatible'],
      [name: 'purge-job-history', version: '1.5', status: 'compatible'],
      [name: 'pwauth', version: '', status: 'unknown'],
      [name: 'redmine', version: '', status: 'unknown'],
      [name: 'restricted-register', version: '', status: 'probably compatible'],
      [name: 'reverse-proxy-auth-plugin', version: '1.7.0', status: 'compatible'],
      [name: 'saml', version: '1.1.7', status: 'compatible'],
      [name: 'scm-sync-configuration', version: '', status: 'mostly compatible'],
      [name: 'script-realm', version: '1.5', status: 'compatible'],
      [name: 'script-security', version: '', status: 'compatible'],
      [name: 'sfee', version: '', status: 'incompatible'],
      [name: 'splunk-devops', version: '1.9.5', status: 'compatible'],
      [name: 'suppress-stack-trace', version: '1.6', status: 'obsolete'],
      [name: 'throttle-concurrents', version: '2.0.3', status: 'compatible'],
      [name: 'url-auth-sso', version: '', status: 'unknown'],
      [name: 'wso2id-oauth', version: '', status: 'unknown'],
      [name: 'wwpass-plugin', version: '', status: 'unknown'],
	  [name: 'jenkins-cloudfoundry-uaa', version: '', status: 'incompatible']
]

def compatiblePluginIssue
def mostlyCompatiblePluginIssue
def probablyCompatiblePluginIssue
def unknownPluginIssue
def obsoletePluginIssue
def warningPluginIssue
def incompatibleluginIssue


println "------------------------- Legend -------------------------"
println "The plugin is fully compatible with the change. Plugin was verified and tested."
println "mostly compatible: The plugin is expected to work correctly. Deep testing was not performed."
println "probably compatible: The plugin might work correctly. Deep testing was not performed."
println "unknown: No check was performed against the plugin."
println "obsolete: The plugin should not be used anymore. No test was performed at all."
println "warning: Special actions must be performed for this plugin before the upgrade."
println "incompatible: The plugin is not compatible and should be removed"
println "------------------------- List of issues -------------------------"

Jenkins.instance.pluginManager.plugins.each {
  compatiblePluginIssue = plugins.find{x -> x.name == it.shortName && x.version > it.version && x.status == 'compatible'}
  mostlyCompatiblePluginIssue = plugins.find{x -> x.name == it.shortName && x.status == 'mostly compatible'}
  probablyCompatiblePluginIssue = plugins.find{x -> x.name == it.shortName && x.status == 'probably compatible'}
  unknownPluginIssue = plugins.find{x -> x.name == it.shortName && x.status == 'unknown'}
  obsoletePluginIssue = plugins.find{x -> x.name == it.shortName && x.status == 'obsolete'}
  warningPluginIssue = plugins.find{x -> x.name == it.shortName && x.status == 'warning'}
  incompatiblePluginIssue = plugins.find{x -> x.name == it.shortName && x.status == 'incompatible'}

  if (compatiblePluginIssue != null) {
    println "[WARNING] " +  it.shortName + " version " + it.version + " is " + compatiblePluginIssue.status + " but it should be upgraded to at least " + compatiblePluginIssue.version
  }

  if (mostlyCompatiblePluginIssue != null) {
    println "[WARNING] " +  it.shortName + " status is " + mostlyCompatiblePluginIssue.status + (mostlyCompatiblePluginIssue.version != '' ? " but it should be upgraded to at least " + mostlyCompatiblePluginIssue.version :"")
  }

  if (probablyCompatiblePluginIssue != null) {
    println "[WARNING] " +  it.shortName + " status is " + probablyCompatiblePluginIssue.status + (probablyCompatiblePluginIssue.version != '' ? " but it should be upgraded to at least " + probablyCompatiblePluginIssue.version :"")
  }

  if (unknownPluginIssue != null) {
    println "[WARNING] " +  it.shortName + " status is " + unknownPluginIssue.status + (unknownPluginIssue.version != '' ? " and it should be upgraded to at least " + unknownPluginIssue.version :"")
  }

  if (obsoletePluginIssue != null) {
    println "[WARNING] " +  it.shortName + " status is " + obsoletePluginIssue.status + (obsoletePluginIssue.version != '' ? " and it should be upgraded to at least " + obsoletePluginIssue.version :"")
  }

  if (warningPluginIssue != null) {
    println "[WARNING] " +  it.shortName + " status is " + warningPluginIssue.status + (warningPluginIssue.version != '' ? " and it should be upgraded to at least " + warningPluginIssue.version :"") + ". Please, read carefully the KB article to check which action items must be performed against this plugin."
  }

  if (incompatiblePluginIssue != null) {
    println "[WARNING] " +  it.shortName + " status is " + incompatiblePluginIssue.status + (incompatiblePluginIssue.version != '' ? " and it should be upgraded to at least " + incompatiblePluginIssue.version :"")
  }
}

println "-------------------------"

Appendix B. Failure stacktraces

LDAP stacktraces

java.lang.IllegalStateException: An attempt to save the global configuration was made before it was loaded
	at jenkins.model.Jenkins.save(Jenkins.java:3381)
	at jenkins.model.Jenkins.saveQuietly(Jenkins.java:3400)
	at jenkins.model.Jenkins.setSecurityRealm(Jenkins.java:2639)
	at jenkins.model.Jenkins$16.run(Jenkins.java:3344)
	at org.jvnet.hudson.reactor.TaskGraphBuilder$TaskImpl.run(TaskGraphBuilder.java:169)
	at org.jvnet.hudson.reactor.Reactor.runTask(Reactor.java:296)
	at jenkins.model.Jenkins$5.runTask(Jenkins.java:1131)
	at org.jvnet.hudson.reactor.Reactor$2.run(Reactor.java:214)
	at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
	at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:68)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused: org.jvnet.hudson.reactor.ReactorException
	at org.jvnet.hudson.reactor.Reactor.execute(Reactor.java:282)
	at jenkins.InitReactorRunner.run(InitReactorRunner.java:49)
	at jenkins.model.Jenkins.executeReactor(Jenkins.java:1164)
	at jenkins.model.Jenkins.<init>(Jenkins.java:962)
	at hudson.model.Hudson.<init>(Hudson.java:85)
	at hudson.model.Hudson.<init>(Hudson.java:81)
	at hudson.WebAppMain$3.run(WebAppMain.java:295)
Caused: hudson.util.HudsonFailedToLoad
	at hudson.WebAppMain$3.run(WebAppMain.java:312)
2021-02-25 12:34:58.637+0000 [id=29]	WARNING	hudson.ExtensionFinder$Sezpoz#scout: Failed to scout hudson.security.LDAPSecurityRealm$DescriptorImpl
java.lang.ClassNotFoundException: org.acegisecurity.ldap.LdapDataAccessException
	at jenkins.util.AntClassLoader.findClassInComponents(AntClassLoader.java:1387)
	at jenkins.util.AntClassLoader.findClass(AntClassLoader.java:1342)
	at jenkins.util.AntClassLoader.loadClass(AntClassLoader.java:1089)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
Caused: java.lang.NoClassDefFoundError: org/acegisecurity/ldap/LdapDataAccessException
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at hudson.ExtensionFinder$Sezpoz.scout(ExtensionFinder.java:727)
	at hudson.ClassicPluginStrategy.findComponents(ClassicPluginStrategy.java:343)
	at hudson.ExtensionList.load(ExtensionList.java:381)
	at hudson.ExtensionList.ensureLoaded(ExtensionList.java:317)
	at hudson.ExtensionList.getComponents(ExtensionList.java:183)
	at jenkins.model.Jenkins$6.onInitMilestoneAttained(Jenkins.java:1161)
	at jenkins.InitReactorRunner$1.onAttained(InitReactorRunner.java:84)
	at org.jvnet.hudson.reactor.ReactorListener$Aggregator.lambda$onAttained$3(ReactorListener.java:102)
	at org.jvnet.hudson.reactor.ReactorListener$Aggregator.run(ReactorListener.java:109)
	at org.jvnet.hudson.reactor.ReactorListener$Aggregator.onAttained(ReactorListener.java:102)
	at org.jvnet.hudson.reactor.Reactor$1.run(Reactor.java:177)
	at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
	at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:68)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
2021-02-25 12:34:59.479+0000 [id=29]	WARNING	h.ExtensionFinder$GuiceFinder$SezpozModule#configure: Failed to load hudson.security.LDAPSecurityRealm$DescriptorImpl
java.lang.ClassNotFoundException: org.acegisecurity.ldap.LdapDataAccessException
	at jenkins.util.AntClassLoader.findClassInComponents(AntClassLoader.java:1387)
	at jenkins.util.AntClassLoader.findClass(AntClassLoader.java:1342)
	at jenkins.util.AntClassLoader.loadClass(AntClassLoader.java:1089)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
Caused: java.lang.NoClassDefFoundError: org/acegisecurity/ldap/LdapDataAccessException
	at java.lang.Class.getDeclaredConstructors0(Native Method)
	at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
	at java.lang.Class.getDeclaredConstructors(Class.java:2020)
	at hudson.ExtensionFinder$GuiceFinder$SezpozModule.resolve(ExtensionFinder.java:495)
	at hudson.ExtensionFinder$GuiceFinder$SezpozModule.resolve(ExtensionFinder.java:482)
	at hudson.ExtensionFinder$GuiceFinder$SezpozModule.configure(ExtensionFinder.java:525)
	at com.google.inject.AbstractModule.configure(AbstractModule.java:62)
	at com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:340)
	at com.google.inject.spi.Elements.getElements(Elements.java:110)
	at com.google.inject.internal.InjectorShell$Builder.build(InjectorShell.java:138)
	at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:104)
	at com.google.inject.Guice.createInjector(Guice.java:96)
	at com.google.inject.Guice.createInjector(Guice.java:73)
	at hudson.ExtensionFinder$GuiceFinder.<init>(ExtensionFinder.java:285)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at net.java.sezpoz.IndexItem.instance(IndexItem.java:181)
	at hudson.ExtensionFinder$Sezpoz._find(ExtensionFinder.java:703)
	at hudson.ExtensionFinder$Sezpoz.find(ExtensionFinder.java:689)
	at hudson.ClassicPluginStrategy.findComponents(ClassicPluginStrategy.java:349)
	at hudson.ExtensionList.load(ExtensionList.java:381)
	at hudson.ExtensionList.ensureLoaded(ExtensionList.java:317)
	at hudson.ExtensionList.getComponents(ExtensionList.java:183)
	at jenkins.model.Jenkins$6.onInitMilestoneAttained(Jenkins.java:1161)
	at jenkins.InitReactorRunner$1.onAttained(InitReactorRunner.java:84)
	at org.jvnet.hudson.reactor.ReactorListener$Aggregator.lambda$onAttained$3(ReactorListener.java:102)
	at org.jvnet.hudson.reactor.ReactorListener$Aggregator.run(ReactorListener.java:109)
	at org.jvnet.hudson.reactor.ReactorListener$Aggregator.onAttained(ReactorListener.java:102)
	at org.jvnet.hudson.reactor.Reactor$1.run(Reactor.java:177)
	at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
	at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:68)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

Active directory stacktraces

2021-02-25 11:44:31.193+0000 [id=30]	WARNING	jenkins.model.Jenkins$5#runTask: Finalizing set up failed perhaps due to plugin dependency issues
java.lang.ClassNotFoundException: hudson.util.spring.BeanBuilder
	at jenkins.util.AntClassLoader.findClassInComponents(AntClassLoader.java:1387)
	at jenkins.util.AntClassLoader.findClass(AntClassLoader.java:1342)
	at jenkins.util.AntClassLoader.loadClass(AntClassLoader.java:1089)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
Caused: java.lang.NoClassDefFoundError: hudson/util/spring/BeanBuilder
	at hudson.plugins.active_directory.ActiveDirectorySecurityRealm.createSecurityComponents(ActiveDirectorySecurityRealm.java:335)
	at hudson.security.SecurityRealm.getSecurityComponents(SecurityRealm.java:550)
	at hudson.security.HudsonFilter.reset(HudsonFilter.java:135)
	at jenkins.model.Jenkins.setSecurityRealm(Jenkins.java:2629)
	at jenkins.model.Jenkins$16.run(Jenkins.java:3344)
	at org.jvnet.hudson.reactor.TaskGraphBuilder$TaskImpl.run(TaskGraphBuilder.java:169)
	at org.jvnet.hudson.reactor.Reactor.runTask(Reactor.java:296)
	at jenkins.model.Jenkins$5.runTask(Jenkins.java:1131)
	at org.jvnet.hudson.reactor.Reactor$2.run(Reactor.java:214)
	at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
	at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:68)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

Reverse Proxy Authentication stack traces

java.lang.IllegalStateException: An attempt to save the global configuration was made before it was loaded
	at jenkins.model.Jenkins.save(Jenkins.java:3381)
	at jenkins.model.Jenkins.saveQuietly(Jenkins.java:3400)
	at jenkins.model.Jenkins.setSecurityRealm(Jenkins.java:2639)
	at jenkins.model.Jenkins$16.run(Jenkins.java:3344)
	at org.jvnet.hudson.reactor.TaskGraphBuilder$TaskImpl.run(TaskGraphBuilder.java:169)
	at org.jvnet.hudson.reactor.Reactor.runTask(Reactor.java:296)
	at jenkins.model.Jenkins$5.runTask(Jenkins.java:1131)
	at org.jvnet.hudson.reactor.Reactor$2.run(Reactor.java:214)
	at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
	at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:68)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused: org.jvnet.hudson.reactor.ReactorException
	at org.jvnet.hudson.reactor.Reactor.execute(Reactor.java:282)
	at jenkins.InitReactorRunner.run(InitReactorRunner.java:49)
	at jenkins.model.Jenkins.executeReactor(Jenkins.java:1164)
	at jenkins.model.Jenkins.<init>(Jenkins.java:962)
	at hudson.model.Hudson.<init>(Hudson.java:85)
	at hudson.model.Hudson.<init>(Hudson.java:81)
	at hudson.WebAppMain$3.run(WebAppMain.java:295)
Caused: hudson.util.HudsonFailedToLoad
	at hudson.WebAppMain$3.run(WebAppMain.java:312)
2021-02-25 12:23:03.104+0000 [id=30]	WARNING	h.ExtensionFinder$GuiceFinder$FaultTolerantScope$1#error: Failed to instantiate Key[type=org.jenkinsci.plugins.reverse_proxy_auth.ReverseProxySecurityRealm$ProxyLDAPDescriptor, annotation=[none]]; skipping this component
java.lang.ClassNotFoundException: org.acegisecurity.userdetails.ldap.LdapUserDetails
	at jenkins.util.AntClassLoader.findClassInComponents(AntClassLoader.java:1387)
	at jenkins.util.AntClassLoader.findClass(AntClassLoader.java:1342)
	at jenkins.util.AntClassLoader.loadClass(AntClassLoader.java:1089)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
Caused: java.lang.NoClassDefFoundError: org/acegisecurity/userdetails/ldap/LdapUserDetails
	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
	at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
	at java.lang.Class.getMethod0(Class.java:3018)
	at java.lang.Class.getMethod(Class.java:1784)
	at hudson.model.Descriptor.<init>(Descriptor.java:295)
	at org.jenkinsci.plugins.reverse_proxy_auth.ReverseProxySecurityRealm$ProxyLDAPDescriptor.<init>(ReverseProxySecurityRealm.java:728)
	at org.jenkinsci.plugins.reverse_proxy_auth.ReverseProxySecurityRealm$ProxyLDAPDescriptor$$FastClassByGuice$$b2bc1c35.newInstance(<generated>)
	at com.google.inject.internal.cglib.reflect.$FastConstructor.newInstance(FastConstructor.java:40)
	at com.google.inject.internal.DefaultConstructionProxyFactory$1.newInstance(DefaultConstructionProxyFactory.java:61)
	at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:105)
	at com.google.inject.internal.ConstructorInjector.access$000(ConstructorInjector.java:32)
	at com.google.inject.internal.ConstructorInjector$1.call(ConstructorInjector.java:89)
	at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:115)
	at hudson.ExtensionFinder$GuiceFinder$SezpozModule.onProvision(ExtensionFinder.java:566)
	at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:126)
	at com.google.inject.internal.ProvisionListenerStackCallback.provision(ProvisionListenerStackCallback.java:68)
	at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:87)
	at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:267)
	at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
	at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
	at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
Caused: com.google.inject.ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, java.lang.NoClassDefFoundError: org/acegisecurity/userdetails/ldap/LdapUserDetails
  at org.jenkinsci.plugins.reverse_proxy_auth.ReverseProxySecurityRealm$ProxyLDAPDescriptor.<init>(ReverseProxySecurityRealm.java:728)