3

I am working on an automation where I need to install sonatype nexus using ansible playbook, and create a nexus user and role.

So far I have installed sonatype nexus using playbook, and also I am able to login to the application and create a "nexus local user". However, I would like to automate the same thing of role and user creation (in nexus) using ansible playbook.

I would appreciate the help.

Jagdish0886
  • 343
  • 1
  • 5
  • 20
  • I don't think so there is any module that will directly create the user in sonatype nexus. you have to either use the api if available from nexus – error404 Sep 17 '19 at 11:56
  • true, yes there is a api available, i am making use of those. you can see it in below comment – Jagdish0886 Sep 17 '19 at 13:26

1 Answers1

2

You can have a look at the ansible-thoteam.nexus3-oss role on galaxy or on github which installs nexus3 and takes care of its provisioning. To be perfectly transparent, I am the current maintainer of this opensource role.

You will want to have a look at the following groovy script to create users (pasted below as a full example):

import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import groovy.transform.Field
import org.sonatype.nexus.security.role.RoleIdentifier
import org.sonatype.nexus.security.user.InvalidCredentialsException
import org.sonatype.nexus.security.user.UserManager
import org.sonatype.nexus.security.user.UserNotFoundException
import org.sonatype.nexus.security.user.User

List<Map<String, String>> actionDetails = []
@Field Map scriptResults = [changed: false, error: false]
scriptResults.put('action_details', actionDetails)
authManager = security.securitySystem.getAuthorizationManager(UserManager.DEFAULT_SOURCE)

def updateUser(userDef, currentResult) {
    User user = security.securitySystem.getUser(userDef.username)

    user.setFirstName(userDef.first_name)
    user.setLastName(userDef.last_name)
    user.setEmailAddress(userDef.email)

    if (user != security.securitySystem.getUser(userDef.username)) {
        security.securitySystem.updateUser(user)
        currentResult.put('status', 'updated')
        scriptResults['changed'] = true
    }

    Set<RoleIdentifier> existingRoles = user.getRoles()
    Set<RoleIdentifier> definedRoles = []
    userDef.roles.each { roleDef ->
        RoleIdentifier role = new RoleIdentifier("default", authManager.getRole(roleDef).roleId);
        definedRoles.add(role)
    }
    if (! existingRoles.equals(definedRoles)) {
        security.securitySystem.setUsersRoles(user.getUserId(), "default", definedRoles)
        currentResult.put('status', 'updated')
        scriptResults['changed'] = true
    }

    try {
        security.securitySystem.changePassword(userDef.username, userDef.password, userDef.password)
    } catch (InvalidCredentialsException ignored) {
        security.securitySystem.changePassword(userDef.username, userDef.password)
        currentResult.put('status', 'updated')
        scriptResults['changed'] = true
    }
    log.info("Updated user {}", userDef.username)
}

def addUser(userDef, currentResult) {
    try {
        security.addUser(userDef.username, userDef.first_name, userDef.last_name, userDef.email, true, userDef.password, userDef.roles)
        currentResult.put('status', 'updated')
        scriptResults['changed'] = true
        log.info("Created user {}", userDef.username)
    } catch (Exception e) {
        currentResult.put('status', 'error')
        currentResult.put('error_msg', e.toString())
        scriptResults['error'] = true
    }
}

def deleteUser(userDef, currentResult) {
    try {
        security.securitySystem.deleteUser(userDef.username, UserManager.DEFAULT_SOURCE)
        log.info("Deleted user {}", userDef.username)
        currentResult.put('status', 'deleted')
        scriptResults['changed'] = true
    } catch (UserNotFoundException ignored) {
        log.info("Delete user: user {} does not exist", userDef.username)
    } catch (Exception e) {
        currentResult.put('status', 'error')
        currentResult.put('error_msg', e.toString())
        scriptResults['error'] = true
    }
}

/* Main */

parsed_args = new JsonSlurper().parseText(args)

parsed_args.each { userDef ->

    state = userDef.get('state', 'present')

    Map<String, String> currentResult = [username: userDef.username, state: state]
    currentResult.put('status', 'no change')

    if (state == 'absent') {
        deleteUser(userDef, currentResult)
    } else {
        try {
            updateUser(userDef, currentResult)
        } catch (UserNotFoundException ignored) {
            addUser(userDef, currentResult)
        } catch (Exception e) {
            currentResult.put('status', 'error')
            currentResult.put('error_msg', e.toString())
            scriptResults['error'] = true
        }
    }

    scriptResults['action_details'].add(currentResult)
}

return JsonOutput.toJson(scriptResults)

This script is expecting to receive a list of users. You can refer to README.md as well as the default vars for details on the expected data structure which looks like this:

nexus_local_users: 
  - username: my_user
    first_name: my
    last_name: user
    email: my@user.com
    password: "s3cr3t"
    roles:
      - developers

I will not paste the full examples again but there is also a groovy script and a data structure for roles

You can have a look at the rest of the role for more information, more specifically the tasks to declare the script in nexus and to call it with its parameters

Even if you don't want to use the full role, this is still in my opinion a good starting example to develop you own solution if you wish.

Hope it can help.

lepe
  • 24,677
  • 9
  • 99
  • 108
Zeitounator
  • 38,476
  • 7
  • 53
  • 66
  • thank you so much @ Zeitounator, I started making use of this role from git hub repo. I find it very useful and i am making modifications to it to customize for my own use. one question, (this is out of curiosity) i have is that role a official page of nexus? because the files and code is very comprehensive and highly useful for all sorts of requirements. – Jagdish0886 Sep 17 '19 at 13:25
  • 1
    This role has absolutely no relation with sonatype. As explained in the history/credit section of the README, It was forked from a [former role by savoir-faire-linux](https://github.com/savoirfairelinux/ansible-nexus3-oss) after an announcement of end-of-maintenance. This former role previously had some [highlights on the sonatype blog](https://community.sonatype.com/t/nexus-repository-3-ansible-role/1256). As you will see the roles have totally diverged. – Zeitounator Sep 17 '19 at 13:38
  • thank you, got it, the role you maintain is a master work. – Jagdish0886 Sep 17 '19 at 13:50