gecos-team/gecoscc-ui

View on GitHub
gecoscc/commands/create_chef_administrator.py

Summary

Maintainability
B
6 hrs
Test Coverage
#
# Copyright 2013, Junta de Andalucia
# http://www.juntadeandalucia.es/
#
# Authors:
#   Emilio Sanchez <emilio.sanchez@gmail.com>
#   Pablo Martin <goinnn@gmail.com>
#
# All rights reserved - EUPL License V 1.1
# https://joinup.ec.europa.eu/software/page/eupl/licence-eupl
#

from builtins import range
import os
import sys
import subprocess

from chef.exceptions import ChefServerNotFoundError, ChefServerError
from getpass import getpass
from optparse import make_option

from gecoscc.management import BaseCommand
from gecoscc.userdb import UserAlreadyExists
from gecoscc.utils import (_get_chef_api, create_chef_admin_user,
                           password_generator, toChefUsername)


class Command(BaseCommand):
    description = """
       Create an admin user into the local adminusers database and into
       the defined chef server.

       If you provide the -n option, a password is generated and printed to
       the shell.
    """

    usage = ("usage: %prog config_uri create_chef_administrator --username user"
             " --email user@example.com --administrator user --key file.pem")

    option_list = [
        make_option(
            '-u', '--username',
            dest='username',
            action='store',
            help='The user username'
        ),
        make_option(
            '-e', '--email',
            dest='email',
            action='store',
            help='The email username'
        ),
        make_option(
            '-n', '--noinput',
            dest='noinput',
            action='store_true',
            default=False,
            help="Don't ask the password"
        ),
        make_option(
            '-a', '--administrator',
            dest='chef_username',
            action='store',
            help='An existing chef administrator username'
        ),
        make_option(
            '-k', '--key',
            dest='chef_pem',
            action='store',
            help='The pem file that contains the chef administrator private key'
        ),
        make_option(
            '-s', '--is-superuser',
            dest='is_superuser',
            action='store_true',
            default=False,
            help="is superuser?"
        ),
    ]

    required_options = (
        'username',
        'email',
        'chef_username',
        'chef_pem',
    )

    def get_pem_for_username(self, username):
        first_boot_media = self.settings.get('firstboot_api.media')
        user_media = os.path.join(first_boot_media, toChefUsername(username))
        if not os.path.exists(user_media):
            os.makedirs(user_media)
        return os.path.join(user_media, 'chef_user.pem')

    def create_password(self, msg_input, msg_noinput):
        if not self.options.noinput:
            password = None
            for _n in range(3):
                print(msg_input)
                password_1 = getpass("password [1]: ").strip()
                password_2 = getpass("password [2]: ").strip()
                if password_1 and password_2 and password_1 == password_2:
                    password = password_1
                    break
                else:
                    print("Both passwords doesn't match or any of them is"
                          " empty\n")
            if not password:
                print("You can't set the password, please retry later")
                sys.exit(1)
        else:
            password = password_generator()
            print(msg_noinput.format(password))
        return password

    def command(self):
        api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem,
                            self.settings.get('chef.ssl.verify'),
                            self.settings.get('chef.version'))
        try:
            api['/users/%s' % toChefUsername(self.options.username)]
            print("The username %s already exists in the chef sever"%(
                toChefUsername(self.options.username)))
            sys.exit(1)
        except ChefServerNotFoundError:
            pass

        chef_password = self.create_password(
            "Insert the chef password, the spaces will be stripped",
            "The generated password to chef server is: {0}")
        try:
            create_chef_admin_user(api, self.settings, toChefUsername(
                self.options.username), chef_password, self.options.email)
        except ChefServerError as e:
            print("User not created in chef, error was: %s" % e)
            sys.exit(1)

        print("User %s created in chef server" % toChefUsername(
            self.options.username))

        if int(self.settings.get('chef.version').split('.')[0]) >= 12:
            if os.path.isfile('/opt/opscode/bin/chef-server-ctl') is True:
                # Include the user in the "server-admins" group
                cmd = ['/opt/opscode/bin/chef-server-ctl',
                       'grant-server-admin-permissions',
                       toChefUsername(self.options.username)]
                if subprocess.call(cmd) != 0:
                    print('ERROR: error adding the administrator to '
                          '"server-admins" chef group')        
                    sys.exit(1)
            else:
                # Chef 12 /opt/opscode/bin/chef-server-ctl does not exists
                # in the system
                # This usually is because Chef and GECOS CC are installed in
                # different machines
                print("NOTICE: Please remember to grant server admin "
                      "permissions to this user by executing the following "
                      "command in Chef 12 server:")
                print("%s %s %s"%('/opt/opscode/bin/chef-server-ctl',
                                  'grant-server-admin-permissions',
                                  toChefUsername(self.options.username)))
            
            # Add the user to the default organization
            try:
                data = {"user": toChefUsername(self.options.username)}
                response = api.api_request('POST',
                    '/organizations/default/association_requests', data=data) 
                association_id = response["uri"].split("/")[-1]         

                api.api_request('PUT', '/users/%s/association_requests/%s'%(
                    toChefUsername(self.options.username), association_id),
                    data={ "response": 'accept' }) 
                
            except ChefServerError as e:
                print("User not added to default organization in chef,", 
                      "error was: %s" % e)
                sys.exit(1)
                
            # Add the user to the default organization's admins group
            try:
                admins_group = api['/organizations/default/groups/admins']
                admins_group['users'].append(toChefUsername(
                    self.options.username))
                api.api_request('PUT', '/organizations/default/groups/admins',
                                data={ "groupname": admins_group["groupname"], 
                    "actors": {
                        "users": admins_group['users'],
                        "groups": admins_group["groups"]
                    }
                    })                 
                
            except ChefServerError as e:
                print("User not added to default organization's admins group"\
                      " in chef, error was: %s" % e)
                sys.exit(1)                
            
            print("User %s set as administrator in the default organization"\
                  " chef server" % toChefUsername(self.options.username))
            

        gcc_password = self.create_password(
            "Insert the GCC password, the spaces will be stripped",
            "The generated password to GCC is: {0}")
        try:
            self.pyramid.userdb.create_user(
                self.options.username,
                gcc_password,
                self.options.email,
                {'is_superuser': self.options.is_superuser}
            )
        except UserAlreadyExists:
            print("The user already exists in mongo")
        else:
            print("User %s created in mongo" % self.options.username)