Issue with LdapConfiguration

So I’ve recently updated to the latest docker container Nexus OSS 3.20.0
Now I’m facing an error when trying to create a new LdapConfiguration

When running
def ldapConfig = new LdapConfiguration()

I get the error
You cannot create an instance from the abstract interface 'org.sonatype.nexus.ldap.persist.entity.LdapConfiguration'.\n @ line 12, column 1.\n new LdapConfiguration()

I tried downgrading and it works

Did something change for this from 3.19.1 -> 3.20.0

Welcome to the Community forum, Jeffrey!

I am investigating to see if this is a known regression. In the meantime, can you tell me from which log file or other output you receive that error?

I’m receiving this output when I try to run the uploaded script with the specified payload to Nexus.

This error output also happens on the log of the Nexus server.

Jeffrey,

There was a change to that class, as you surmise. It was changed from a concrete class to an interface. Can you post your script on this thread so we can help you update it? You can also PM it to me if you are more comfortable with that option.

1 Like

Thanks Andrés,

This isn’t my script it’s located here but I’m using it.

import org.sonatype.nexus.ldap.persist.LdapConfigurationManager
import org.sonatype.nexus.ldap.persist.entity.LdapConfiguration
import org.sonatype.nexus.ldap.persist.entity.Connection
import org.sonatype.nexus.ldap.persist.entity.Mapping
import groovy.json.JsonSlurper

parsed_args = new JsonSlurper().parseText(args)


def ldapConfigMgr = container.lookup(LdapConfigurationManager.class.getName());

def ldapConfig = new LdapConfiguration()
boolean update = false;

// Look for existing config to update
ldapConfigMgr.listLdapServerConfigurations().each {
    if (it.name == parsed_args.name) {
        ldapConfig = it
        update = true
    }
}

ldapConfig.setName(parsed_args.name)

// Connection
connection = new Connection()
connection.setHost(new Connection.Host(Connection.Protocol.valueOf(parsed_args.protocol), parsed_args.hostname, Integer.valueOf(parsed_args.port)))
if (parsed_args.auth == "simple") {
    connection.setAuthScheme("simple")
    connection.setSystemUsername(parsed_args.username)
    connection.setSystemPassword(parsed_args.password)
} else {
    connection.setAuthScheme("none")
}
connection.setSearchBase(parsed_args.search_base)
connection.setConnectionTimeout(30)
connection.setConnectionRetryDelay(300)
connection.setMaxIncidentsCount(3)
connection.setUseTrustStore(Boolean.valueOf(parsed_args.use_trust_store))
ldapConfig.setConnection(connection)


// Mapping
mapping = new Mapping()
mapping.setUserBaseDn(parsed_args.user_base_dn)
mapping.setLdapFilter(parsed_args.user_ldap_filter)
mapping.setUserObjectClass(parsed_args.user_object_class)
mapping.setUserIdAttribute(parsed_args.user_id_attribute)
mapping.setUserRealNameAttribute(parsed_args.user_real_name_attribute)
mapping.setEmailAddressAttribute(parsed_args.user_email_attribute)

if (parsed_args.map_groups_as_roles) {
    if(parsed_args.map_groups_as_roles_type == "static"){
        mapping.setLdapGroupsAsRoles(true)
        mapping.setGroupBaseDn(parsed_args.group_base_dn)
        mapping.setGroupObjectClass(parsed_args.group_object_class)
        mapping.setGroupIdAttribute(parsed_args.group_id_attribute)
        mapping.setGroupMemberAttribute(parsed_args.group_member_attribute)
        mapping.setGroupMemberFormat(parsed_args.group_member_format)
    } else if (parsed_args.map_groups_as_roles_type == "dynamic") {
        mapping.setLdapGroupsAsRoles(true)
        mapping.setUserMemberOfAttribute(parsed_args.user_memberof_attribute)
    }
}

mapping.setUserSubtree(parsed_args.user_subtree)
mapping.setGroupSubtree(parsed_args.group_subtree)

ldapConfig.setMapping(mapping)


if (update) {
    ldapConfigMgr.updateLdapServerConfiguration(ldapConfig)
} else {
    ldapConfigMgr.addLdapServerConfiguration(ldapConfig)
}

We are familiar with that repository, but are not the maintainers.

Looks like there are already two PRs which address this change:

My suggestion is that you stick with 3.19.1 for a couple of days longer until they merge those changes.

1 Like

Thank you for the quick reply and the help!

Of course! Glad to help.

Hi. I am the maintainer of the above mentioned repository. For anyone who would pass by, this is the solution we found after trial and error on my side and help from my users.

The base problem was:

def ldapConfiguration = new LdapConfiguration()

which is now an interface and cannot be instanciated anymore as explained by @andrés above.

First try to fix:

def ldapConfigMgr = container.lookup(LdapConfigurationManager.class.getName())
def ldapConfig = ldapConfigMgr.getConfiguration()

This was mostly working except that the following line:

ldapConfig.setName(parsed_args.name)

was firing an error

No signature of method: java.util.LinkedHashMap.setName() is applicable for argument types: (java.lang.String)

Second try (good one):

def ldapConfigMgr = container.lookup(LdapConfigurationManager.class.getName())
def ldapConfig = ldapConfigMgr.newConfiguration()
ldapConfig.setName(parsed_args.name)

Subsidiary questions to community

I maintain this script as part of an ansible role to automate deployment and provisionning of nexus. I inherited this role from the previous author at @savoir-faire-linux. It worked, I almost never touched it (some PR included new params that where missing…). I don’t even know where the original script comes from and how someone was able to craft it without any documentation or code. And I am not at all a groovy/java expert.

I understand that all ldap.* classes are internal and that I should expect them to change without prior notice. But is there any way we can get basic information of the available methods and their expected params ? Because this one was a (too) long bake.

Thanks in advance for your response.

Nexus Repository Manager 3 now has a beta REST API. Groovy scripting has always been potentially dangerous since we may change our internal classes at any time. Ideally, where possible, it’s best to use our REST APIs since they won’t change once we release them as v1 and they are the supported way to configure Nexus Repository Manager. At a quick glance I don’t think that script is doing anything the REST API doesn’t support which would let you use whatever tooling you are comfortable with instead of some groovy script you know nothing about.

1 Like

@mmartz I had missed all those ldap endpoints entered the REST API. Thanks for your return. Indeed that definitely looks like the way to go.