def command(self):
        api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem)
        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)
        except ChefServerError, e:
            print "User not created in chef, error was: %s" % e
            sys.exit(1)
Example #2
0
def _check_if_user_belongs_to_admin_group(request, organization, username):
    chefusername = toChefUsername(username)
    settings = get_current_registry().settings
    api = get_chef_api(settings, request.user)

    admins_group = api['/organizations/%s/groups/admins' % (organization)]
    if not chefusername in admins_group:
        # Check if exists an association request for this user
        assoc_requests = None
        try:
            assoc_requests = api['/organizations/%s/association_requests' %
                                 (organization)]
        except ChefServerNotFoundError:
            pass

        association_id = None
        for req in assoc_requests:
            if req["username"] == chefusername:
                association_id = req["id"]

        if association_id is None:
            # Set an association request for the user in that organization
            try:
                data = {"user": chefusername}
                response = api.api_request(
                    'POST',
                    '/organizations/%s/association_requests' % (organization),
                    data=data)
                association_id = response["uri"].split("/")[-1]
            except ChefServerError:
                # Association already exists?
                pass

        if association_id is not None:
            # Accept the association request
            logger.info('Adding %s user to default organization' % (username))
            api.api_request('PUT',
                            '/users/%s/association_requests/%s' %
                            (chefusername, association_id),
                            data={"response": 'accept'})

        # Add the user to the group
        logger.info('Adding %s user to admins group' % (username))
        admins_group['users'].append(chefusername)
        api.api_request('PUT',
                        '/organizations/%s/groups/admins' % (organization),
                        data={
                            "groupname": admins_group["groupname"],
                            "actors": {
                                "users": admins_group['users'],
                                "groups": admins_group["groups"]
                            }
                        })
Example #3
0
 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'))
     ou_name = 'ou_0'
     ou = self.create_root_ou(ou_name)
     for node_id in ChefNode.list():
         try:
             node_mongo_id = register_or_updated_node(api, node_id, ou, self.db.nodes)
         except DuplicateKeyError:
             node_mongo_id = update_node(api, node_id, ou, self.db.nodes)
         if not node_mongo_id:
             print "%s does not exists" % node_id
    def command(self):
        api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem)
        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)
        except ChefServerError, e:
            print "User not created in chef, error was: %s" % e
            sys.exit(1)
Example #5
0
 def command(self):
     api = _get_chef_api(self.settings.get('chef.url'),
                         toChefUsername(self.options.chef_username),
                         self.options.chef_pem)
     ou_name = 'ou_0'
     ou = self.create_root_ou(ou_name)
     for node_id in ChefNode.list():
         try:
             node_mongo_id = register_or_updated_node(
                 api, node_id, ou, self.db.nodes)
         except DuplicateKeyError:
             node_mongo_id = update_node(api, node_id, ou, self.db.nodes)
         if not node_mongo_id:
             print "%s does not exists" % node_id
Example #6
0
 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.version'))
                         
     print('INFO: Update IPv4 address START!') 
     db = self.pyramid.db
     computers = db.nodes.find({'type': 'computer'})
     for comp in computers:
         node_id = comp.get('node_chef_id', None)
         node = Node(node_id, api)
         ipaddress = node.attributes.get('ipaddress')
         
         print('INFO: Update node: %s, set IP: %s'%(node_id, ipaddress)) 
         db.nodes.update({'node_chef_id':node_id},{'$set': {'ipaddress':ipaddress}})
     
     print('INFO: Update IPv4 address END!') 
    def command(self):

        collection = self.db.serviceproviders
        sp_model = ServiceProvider()

        chef_ssl_verify = True if self.settings.get(
            'chef.ssl.verify') == "True" else False

        api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, chef_ssl_verify,
                            self.settings.get('chef.version'))
        cookbook_name = self.settings['chef.cookbook_name']

        cookbook = get_cookbook(api, cookbook_name)

        for f in cookbook['files']:
            if f['name'] == 'serviceproviders.xml':
                try:
                    xml = requests.get(f['url'], verify=chef_ssl_verify)
                    break
                except requests.exceptions.RequestException as e:
                    print e
                    sys.exit(1)

        # Parsing XML
        root = ET.fromstring(xml.text)
        for country in root.findall('country'):

            for providername in country.findall('provider/name'):

                if providername.text:
                    try:
                        new_sp = sp_model.serialize({
                            'name':
                            country.get('code').lower(),
                            'provider':
                            providername.text
                        })
                        print new_sp
                        collection.insert(new_sp)
                    except:
                        print "ERROR:" + providername.text
Example #8
0
def _check_if_user_belongs_to_admin_group(request, organization, username):
    chefusername = toChefUsername(username)
    settings = get_current_registry().settings
    api = get_chef_api(settings, request.user)
    
    admins_group = api['/organizations/%s/groups/admins'%(organization)]
    if not chefusername in admins_group:
        # Check if exists an association request for this user
        assoc_requests = None
        try:
            assoc_requests = api['/organizations/%s/association_requests'%(organization)]
        except ChefServerNotFoundError:
            pass                    
        
        association_id = None
        for req in assoc_requests:
            if req["username"] == chefusername:
                association_id = req["id"]
        
        if association_id is None:
            # Set an association request for the user in that organization
            try:
                data = {"user": chefusername}
                response = api.api_request('POST', '/organizations/%s/association_requests'%(organization), data=data) 
                association_id = response["uri"].split("/")[-1]
            except ChefServerError:
                # Association already exists?
                pass                    

        if association_id is not None:
            # Accept the association request
            logger.info('Adding %s user to default organization'%(username))
            api.api_request('PUT', '/users/%s/association_requests/%s'%(chefusername, association_id),  data={ "response": 'accept' }) 

        # Add the user to the group
        logger.info('Adding %s user to admins group'%(username))
        admins_group['users'].append(chefusername)
        api.api_request('PUT', '/organizations/%s/groups/admins'%(organization), data={ "groupname": admins_group["groupname"], 
            "actors": {
                "users": admins_group['users'],
                "groups": admins_group["groups"]
            }
            })         
    def command(self):

        collection = self.db.serviceproviders
        sp_model = ServiceProvider()

        chef_ssl_verify = True if self.settings.get('chef.ssl.verify') == "True" else False

        api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, chef_ssl_verify, self.settings.get('chef.version'))
        cookbook_name = self.settings['chef.cookbook_name']

        cookbook = get_cookbook(api, cookbook_name)

        for f in cookbook['files']:
            if f['name'] == 'serviceproviders.xml': 
                try:
                    xml = requests.get(f['url'], verify=chef_ssl_verify)
                    break
                except requests.exceptions.RequestException as e:
                    print e
                    sys.exit(1)

        # Parsing XML
        root = ET.fromstring(xml.text)
        for country in root.findall('country'):

            for providername in country.findall('provider/name'):

                if providername.text:
                    try:
                        new_sp=sp_model.serialize({'name': country.get('code').lower(), 'provider': providername.text})
                        print new_sp
                        collection.insert(new_sp)
                    except:
                        print "ERROR:" + providername.text
Example #10
0
    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'))
        cookbook_name = self.settings['chef.cookbook_name']

        cookbook = get_cookbook(api, cookbook_name)

        languages = self.settings.get('pyramid.locales')
        languages.remove(self.settings.get('pyramid.default_locale_name'))

        policies = {}
        try:
            for key, value in cookbook['metadata']['attributes']['json_schema']['object']['properties']['gecos_ws_mgmt']['properties'].items():
                for k, policy in value['properties'].items():
                    policy['path'] = '%s.%s.%s' % (cookbook_name, key, k)
                    policies[k] = policy
        except KeyError:
            print "Can not found policies in cookbook %s" % cookbook_name
            sys.exit(1)

        policies_to_import = self.options.policies
        if policies_to_import:
            found = set(policies_to_import).intersection(set(policies.keys()))
            not_found = set(policies_to_import).difference(set(policies.keys()))
            if not_found:
                print "%s policies to import. Policies NOT FOUND: %s" % (len(found), list(not_found))
            else:
                print "%s policies to import" % len(found)
        else:
            print "%s policies to import" % len(policies.keys())

        for key, value in policies.items():
            if policies_to_import and key not in policies_to_import:
                continue
            elif key in EXCLUDE_POLICIES:
                continue
            if key == PACKAGE_POLICY:
                self.set_packages_url(value)
            
            if key == MIMETYPES_POLICY:
                self.set_mimetypes_url(value)

            if key == MOBILE_BROADBAND_POLICY:
                self.set_serviceproviders_url(value)

            support_os = value['properties']['support_os']['default']

            for ex_attr in EXCLUDE_GENERIC_ATTRS:
                if ex_attr in value['properties']:
                    del(value['properties'][ex_attr])

            path = value.pop('path')

            form_layout = value.pop('form', {})
            is_mergeable = value.pop('is_mergeable', False)
            autoreverse = value.pop('autoreverse', False)

            if is_user_policy(path):
                targets = ['ou', 'user', 'group']
                title = value['title']
                titles = {}
                for lan in languages:
                    titles[lan] = value['title_' + lan]

                value = value['properties']['users']['patternProperties']['.*']
                if 'updated_by' in value.get('properties', {}):
                    del value['properties']['updated_by']
                value['title'] = title
                for lan in languages:
                    value['title_' + lan] = titles[lan]

            elif 'single_node' in path:
                targets = ['computer']
            else:
                targets = DEFAULT_TARGETS

            policy = {
                'name': value['title'],
                'slug': key,
                'path': path,
                'schema': value,
                'form': form_layout,
                'targets': targets,
                'is_emitter_policy': False,
                'support_os': support_os,
                'is_mergeable': is_mergeable,
                'autoreverse': autoreverse,
            }

            for lan in languages:
                policy['name_' + lan] = value['title_' + lan]

            self.treatment_policy(policy)

        if not self.options.ignore_emitter_policies:
            for emiter in RESOURCES_EMITTERS_TYPES:
                slug = emiter_police_slug(emiter)
                schema = deepcopy(SCHEMA_EMITTER)
                schema['properties']['object_related_list']['title'] = '%s list' % emiter.capitalize()
                for lan in languages:
                    schema['properties']['object_related_list']['title_' + lan] = EMITTER_LIST_LOCALIZED[lan] % EMITTER_LOCALIZED[lan][emiter]
                schema['properties']['object_related_list']['autocomplete_url'] = POLICY_EMITTER_URL[slug]
                policy = {
                    'name': POLICY_EMITTER_NAMES[slug],
                    'slug': slug,
                    'path': POLICY_EMITTER_PATH[slug],
                    'targets': POLICY_EMITTER_TARGETS[slug],
                    'is_emitter_policy': True,
                    'schema': schema,
                    'support_os': policies[POLICY_EMITTER_PATH[slug].split('.')[2]]['properties']['support_os']['default'],
                    'is_mergeable': True,
                    'autoreverse': policies[POLICY_EMITTER_PATH[slug].split('.')[-2]].get('autoreverse', False)
                }
                for lan in languages:
                    policy['name_' + lan] = POLICY_EMITTER_NAMES_LOCALIZED[lan][slug]
                self.treatment_policy(policy)
                
        # Check non imported policies
        print "Check non imported policies..."
        dbpolicies = self.db.policies.find({})
        found = False
        for policy in dbpolicies:
            if (policy['slug'] not in policies and 
                not policy['slug'].endswith('_can_view')):
                print "Policy '%s' wasn't imported. Probably is deprecated." % (policy['slug'])
                found = True
                if self.options.delete:
                    # Delete deprecated policy
                    self.db.policies.remove({'slug': policy['slug']})
                    print "Policy '%s' deleted!" % (policy['slug'])
                    if policy['slug'] == 'package_profile_res':
                        # Also delete software_profiles collection
                        print "Drop software profiles collection!"
                        self.db.software_profiles.drop()
                        self.db.settings.remove({'key' : 'software_profiles'})
                        
        if not found:
            print "There are no deprecated policies"
    def command(self):
        # Initialization
        sanitized = False
        computers = set()
        self.api = _get_chef_api(self.settings.get('chef.url'),
                                 toChefUsername(self.options.chef_username),
                                 self.options.chef_pem, False,
                                 self.settings.get('chef.version'))

        self.auth_user = self.db.adminusers.find_one(
            {'username': self.options.chef_username})
        if self.auth_user is None:
            logger.error('The administrator user must exist in MongoDB')
            sys.exit(1)

        self.db = self.pyramid.db

        # Get local_admin_users_res (Local Administrators) policy
        logger.info(
            'Getting Local Administrators (local_admin_users_res) policy ...')
        policy = self.db.policies.find_one({'slug': 'local_admin_users_res'})
        schema = policy['schema']
        policyId = policy['_id']

        logger.info('schema   = %s' % str(schema))
        logger.info('Id.policy = %s' % str(policyId))

        # Searching nodes with the Local Administrators policy
        # Query Fields of an Embedded Document (Mongo documentation)
        # Example:
        # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}})
        logger.info('Searching nodes with the Local Administrators policy...')
        field = 'policies.' + str(policyId)
        filters = {field: {'$exists': True}}
        nodes = self.db.nodes.find(filters)

        # Validating data and, where appropiate, fixing
        for node in nodes:
            instance = node['policies'][unicode(policyId)]

            logger.info('Node name = %s, _id = %s' %
                        (node['name'], str(node['_id'])))
            logger.info('Instance before validate method: %s' % str(instance))
            while True:
                try:
                    validate(instance, schema)
                    break
                except ValidationError as e:
                    logger.warning('Validation error on instance = %s' %
                                   str(e.message))
                    # Sanitize instance
                    self.sanitize(e, instance)
                    sanitized = True

            if sanitized:
                # Setting false sanitized for next iteration
                sanitized = False
                logger.info('Sanitized instance: %s' % str(instance))

                # Update mongo
                self.db.nodes.update({'_id': node['_id']},
                                     {'$set': {
                                         field: instance
                                     }})

                # Affected nodes
                if node['type'] == 'ou':
                    result = list(
                        self.db.nodes.find(
                            {
                                'path': get_filter_nodes_belonging_ou(
                                    node['_id']),
                                'type': 'computer'
                            }, {'_id': 1}))
                    logger.info('OU computers = %s' % str(result))
                elif node['type'] == 'group':
                    result = list(
                        self.db.nodes.find(
                            {
                                '_id': {
                                    '$in': node['members']
                                },
                                'type': 'computer'
                            }, {'_id': 1}))
                    logger.info('GROUP computers = %s' % str(result))
                elif node['type'] == 'computer':
                    result = [node]
                    logger.info('COMPUTER computers = %s' % str(result))

                [computers.add(str(n['_id'])) for n in result]

        # Removing unused local_admin_remove_list attribute in chef nodes
        for node_id in ChefNode.list():
            node = ChefNode(node_id, self.api)
            logger.info('Checking node: %s' % (node_id))
            attr_dotted = policy['path'] + '.local_admin_remove_list'
            logger.info('Atttribute dotted path: %s' % (attr_dotted))
            if node.attributes.has_dotted(attr_dotted):
                logger.info("Remove 'local_admin_remove_list' attribute!")
                try:
                    logger.info(
                        "node.attributes = %s" %
                        str(node.attributes['gecos_ws_mgmt']['misc_mgmt']
                            ['local_admin_users_res'].to_dict()))
                    delete_dotted(node.attributes, attr_dotted)
                    node.save()
                except:
                    logger.warn(
                        "Problem deleting local_admin_remove_list value from node: %s"
                        % (node_id))
                    logger.warn(
                        "You may be trying to delete a default attribute instead normal attribute: %s"
                        % (node_id))

        for computer in computers:
            logger.info('computer = %s' % str(computer))
            computer = self.db.nodes.find_one({'_id': ObjectId(computer)})
            apply_policies_to_computer(self.db.nodes,
                                       computer,
                                       self.auth_user,
                                       api=self.api,
                                       initialize=False,
                                       use_celery=False)

        logger.info('Finished.')
            # 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, 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
Example #13
0
    def command(self):
        # Initialization
        self.api = _get_chef_api(self.settings.get('chef.url'),
                                 toChefUsername(self.options.chef_username),
                                 self.options.chef_pem, False,
                                 self.settings.get('chef.version'))

        self.db = self.pyramid.db
        self.referenced_data_type = {}
        self.referenced_data_type['storage_can_view'] = 'storage'
        self.referenced_data_type['repository_can_view'] = 'repository'
        self.referenced_data_type['printer_can_view'] = 'printer'

        # Get gecos_ws_mgmt cookbook default data structure
        default_data_dotted_keys = {}
        default_data = self.get_default_data(default_data_dotted_keys)
        if default_data is None:
            logger.error("Can't find default data!")
            return

        # Get all the policies structures
        logger.info('Getting all the policies structures from database...')
        dbpolicies = self.db.policies.find()
        self.policiesdata = {}
        self.slug_check = {}
        for policy in dbpolicies:
            logger.debug('Adding to dictionary: %s => %s' %
                         (policy['_id'], json.dumps(policy['schema'])))
            self.policiesdata[str(policy['_id'])] = policy

            # Check policy slug field (must be unique)
            if policy['slug'] in self.slug_check:
                logger.error("There are more than one policy with '%s' slug!" %
                             (policy['slug']))
            else:
                slug = policy['slug']
                # The slug of the emitter policies is different from the others
                if slug == 'printer_can_view':
                    slug = 'printers_res'
                elif slug == 'storage_can_view':
                    slug = 'user_shared_folders_res'
                elif slug == 'repository_can_view':
                    slug = 'software_sources_res'

                self.slug_check[slug] = policy

            # Check policy serialization
            try:
                logger.debug('Serialized policy: %s' %
                             (json.dumps(Policy().serialize(policy))))
            except Exception as err:
                logger.error(
                    'Policy %s with slug %s can\'t be serialized: %s' %
                    (policy['_id'], policy['slug'], str(err)))
                logger.warn(
                    'Possible cause: New fields in models (Colander) but the import_policies command has not yet been executed to update schema.'
                )

        if self.options.clean_inheritance:
            logger.info('Cleaning inheritance field...')
            self.db.nodes.update({"inheritance": {
                '$exists': True
            }}, {'$unset': {
                "inheritance": {
                    '$exist': True
                }
            }},
                                 multi=True)

        if self.options.clean_variables:
            logger.info('Cleaning variables data from Chef nodes')
            for node_id in ChefNode.list():
                node = ChefNode(node_id, self.api)
                if node.normal.has_dotted('gecos_info'):
                    del node.normal['gecos_info']
                    node.save()

        logger.info('Checking tree...')
        # Look for the root of the nodes tree
        root_nodes = self.db.nodes.find({"path": "root"})
        for root in root_nodes:
            self.check_node_and_subnodes(root)

        logger.info(
            'Checking nodes that are outside the tree (missing OUs in the PATH)...'
        )
        # Check node path
        nodes = self.db.nodes.find({})
        for node in nodes:
            if not 'path' in node:
                logger.error('Node with ID: %s has no "path" attribute!' %
                             (str(node['_id'])))
                continue

            if not 'name' in node:
                logger.error('Node with ID: %s has no "name" attribute!' %
                             (str(node['_id'])))
                continue

            if not 'type' in node:
                logger.error('Node with ID: %s has no "type" attribute!' %
                             (str(node['_id'])))
                continue

            for ou_id in node['path'].split(','):
                if ou_id == 'root':
                    continue

                ou = self.db.nodes.find_one({"_id": ObjectId(ou_id)})
                if not ou:
                    logger.error(
                        'Can\'t find OU %s that belongs to node path (node ID: %s NAME: %s)'
                        % (str(ou_id), str(node['_id']), node['name']))
                    continue

        logger.info('Checking chef node references...')
        # Check the references to Chef nodes
        computers = self.db.nodes.find({"type": "computer"})
        for computer in computers:
            if "node_chef_id" in computer:
                # Check Chef node
                computer_node = ChefNode(computer['node_chef_id'], self.api)
                logger.info("Computer: %s Chef ID: %s" %
                            (computer['name'], computer['node_chef_id']))
                if not computer_node.exists:
                    logger.error("No Chef node with ID %s!" %
                                 (computer['node_chef_id']))

            else:
                logger.error("No Chef ID in '%s' computer!" %
                             (computer['name']))

        logger.info(
            'Checking MongoDB computer references and deprecated policies...')
        # Check the references to computer nodes
        for node_id in ChefNode.list():
            found = False
            computers = self.db.nodes.find({"node_chef_id": node_id})
            node_path = None
            for computer in computers:
                found = True
                node_path = computer['path']

            computer_node = ChefNode(node_id, self.api)
            if not found:
                pclabel = "(No OHAI-GECOS data in the node)"
                try:
                    pclabel = "(pclabel = %s)" % (
                        computer_node.attributes.get_dotted(
                            'ohai_gecos.pclabel'))
                except KeyError:
                    pass

                logger.error("No computer node for Chef ID: '%s' %s!" %
                             (node_id, pclabel))
                logger.warn(
                    "Possible cause: The node has been deleted in Gecos Control Center but not in Chef server, either because it was in use at that time or for another unknown reason."
                )

            # Check default data for chef node
            if not computer_node.default.to_dict(
            ) or not computer_node.attributes.has_dotted('gecos_ws_mgmt'):
                logger.info(
                    "FIXED: For an unknown reason Chef node: %s has no default attributes."
                    % (node_id))
                computer_node.default = default_data
                computer_node.save()

            # Check "updated_by" field
            attributes = computer_node.normal.to_dict()
            updated, updated_attributes = self.check_updated_by_field(
                node_id, None, attributes)
            if updated:
                computer_node.normal = updated_attributes
                computer_node.save()

            updated, updated_attributes = self.check_chef_node_policies(
                node_id, None, attributes)
            if updated:
                computer_node.normal = updated_attributes
                computer_node.save()

            if node_path is not None:
                # Check "gecos_path_ids" field
                if not computer_node.attributes.has_dotted(
                        'gecos_path_ids'
                ) or computer_node.attributes.get_dotted(
                        'gecos_path_ids') != node_path:
                    logger.info(
                        "FIXED: gecos_path_ids attribute in node: %s." %
                        (node_id))
                    computer_node.attributes.set_dotted(
                        'gecos_path_ids', node_path)
                    computer_node.save()

                # Check "gecos_path_names" field
                node_path_names = 'root'
                for elm in node_path.split(','):
                    if elm == 'root':
                        continue
                    ou = self.db.nodes.find_one({'_id': ObjectId(elm)})
                    node_path_names += ',' + ou['name']

                if not computer_node.attributes.has_dotted(
                        'gecos_path_names'
                ) or computer_node.attributes.get_dotted(
                        'gecos_path_names') != node_path_names:
                    logger.info(
                        "FIXED: gecos_path_names attribute in node: %s." %
                        (node_id))
                    computer_node.attributes.set_dotted(
                        'gecos_path_names', node_path_names)
                    computer_node.save()

        logger.info('END ;)')
Example #14
0
    def command(self):
        api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem)
        cookbook_name = self.settings['chef.cookbook_name']

        cookbook = get_cookbook(api, cookbook_name)

        languages = self.settings.get('pyramid.locales')
        languages.remove(self.settings.get('pyramid.default_locale_name'))

        policies = {}
        try:
            for key, value in cookbook['metadata']['attributes']['json_schema']['object']['properties']['gecos_ws_mgmt']['properties'].items():
                for k, policy in value['properties'].items():
                    policy['path'] = '%s.%s.%s' % (cookbook_name, key, k)
                    policies[k] = policy
        except KeyError:
            print "Can not found policies in cookbook %s" % cookbook_name
            sys.exit(1)

        policies_to_import = self.options.policies
        if policies_to_import:
            found = set(policies_to_import).intersection(set(policies.keys()))
            not_found = set(policies_to_import).difference(set(policies.keys()))
            if not_found:
                print "%s policies to import. Policies NOT FOUND: %s" % (len(found), list(not_found))
            else:
                print "%s policies to import" % len(found)
        else:
            print "%s policies to import" % len(policies.keys())

        for key, value in policies.items():
            if policies_to_import and key not in policies_to_import:
                continue
            elif key in EXCLUDE_POLICIES:
                continue
            if key == PACKAGE_POLICY:
                self.set_packages_url(value)
            for ex_attr in EXCLUDE_GENERIC_ATTRS:
                if ex_attr in value['properties']:
                    del(value['properties'][ex_attr])
            path = value.pop('path')

            support_os = value['properties']['support_os']['default']

            del value['properties']['support_os']

            if is_user_policy(path):
                targets = ['ou', 'user', 'group']
                title = value['title']
                titles = {}
                for lan in languages:
                    titles[lan] = value['title_' + lan]

                value = value['properties']['users']['patternProperties']['.*']
                if 'updated_by' in value.get('properties', {}):
                    del value['properties']['updated_by']
                value['title'] = title
                for lan in languages:
                    value['title_' + lan] = titles[lan]

            elif 'network_mgmt' in path:
                targets = ['computer']
            else:
                targets = DEFAULT_TARGETS

            policy = {
                'name': value['title'],
                'slug': key,
                'path': path,
                'schema': value,
                'targets': targets,
                'is_emitter_policy': False,
                'support_os': support_os,
            }

            for lan in languages:
                policy['name_' + lan] = value['title_' + lan]

            self.treatment_policy(policy)

        self.create_software_profiles_policy(policies, languages)

        if not self.options.ignore_emitter_policies:
            for emiter in RESOURCES_EMITTERS_TYPES:
                slug = emiter_police_slug(emiter)
                schema = deepcopy(SCHEMA_EMITTER)
                schema['properties']['object_related_list']['title'] = '%s list' % emiter.capitalize()
                for lan in languages:
                    schema['properties']['object_related_list']['title_' + lan] = EMITTER_LIST_LOCALIZED[lan] % EMITTER_LOCALIZED[lan][emiter]
                schema['properties']['object_related_list']['autocomplete_url'] = POLICY_EMITTER_URL[slug]
                policy = {
                    'name': POLICY_EMITTER_NAMES[slug],
                    'slug': slug,
                    'path': POLICY_EMITTER_PATH[slug],
                    'targets': POLICY_EMITTER_TARGETS[slug],
                    'is_emitter_policy': True,
                    'schema': schema,
                    'support_os': policies[POLICY_EMITTER_PATH[slug].split('.')[2]]['properties']['support_os']['default']
                }
                for lan in languages:
                    policy['name_' + lan] = POLICY_EMITTER_NAMES_LOCALIZED[lan][slug]
                self.treatment_policy(policy)
Example #15
0
    def command(self):
        from gecoscc.api.chef_status import USERS_OLD, USERS_OHAI
        # Initialization
        self.api = _get_chef_api(self.settings.get('chef.url'),
                                 toChefUsername(self.options.chef_username),
                                 self.options.chef_pem, False,
                                 self.settings.get('chef.version'))

        self.db = self.pyramid.db

        # Check administrator user
        auth_user = self.db.adminusers.find_one(
            {'username': self.options.chef_username})
        if auth_user is None:
            logger.error('The administrator user must exist in MongoDB')
            sys.exit(1)

        # Recorriendo todos los nodos
        for node_id in ChefNode.list():
            node = ChefNode(node_id, self.api)
            logger.info('Checking node: %s' % (node_id))

            try:
                if node.attributes.get_dotted(USERS_OLD):
                    delete_dotted(node.attributes, USERS_OLD)
                    node.save()
            except KeyError:
                logger.warn("Not found attribute: %s" % (USERS_OLD))
            except:
                logger.warn(
                    "Problem deleting users_old attribute from node: %s" %
                    (node_id))

            # Updating users list
            computer = self.db.nodes.find_one({
                'node_chef_id': node_id,
                'type': 'computer'
            })
            if not computer:
                logger.error('This node does not exist (mongodb)')
                continue

            chef_node_usernames = set([
                d['username'] for d in node.attributes.get_dotted(USERS_OHAI)
            ])
            gcc_node_usernames = set([
                d['name'] for d in self.db.nodes.find(
                    {
                        'type': 'user',
                        'computers': {
                            '$in': [computer['_id']]
                        }
                    }, {
                        '_id': 0,
                        'name': 1
                    })
            ])

            users_recalculate_policies = []
            users_remove_policies = []

            # Users added/removed ?
            if set.symmetric_difference(chef_node_usernames,
                                        gcc_node_usernames):
                logger.info("Users added/removed found.")

                # Add users or vinculate user to computer if already exists
                addusers = set.difference(chef_node_usernames,
                                          gcc_node_usernames)
                for add in addusers:
                    logger.info("Added user: %s" % (add))
                    user = self.db.nodes.find_one({
                        'name':
                        add,
                        'type':
                        'user',
                        'path':
                        get_filter_in_domain(computer)
                    })

                    if not user:
                        user_model = User()
                        user = user_model.serialize({
                            'name':
                            add,
                            'path':
                            computer.get('path', ''),
                            'type':
                            'user',
                            'lock':
                            computer.get('lock', ''),
                            'source':
                            computer.get('source', '')
                        })

                        user = update_computers_of_user(
                            self.db, user, self.api)

                        del user['_id']
                        user_id = self.db.nodes.insert(user)
                        user = self.db.nodes.find_one({'_id': user_id})
                        users_recalculate_policies.append(user)

                    else:
                        computers = user.get('computers', [])
                        if computer['_id'] not in computers:
                            computers.append(computer['_id'])
                            self.db.nodes.update(
                                {'_id': user['_id']},
                                {'$set': {
                                    'computers': computers
                                }})
                            users_recalculate_policies.append(user)
                            add_computer_to_user(computer['_id'], user['_id'])

                # Removed users
                delusers = set.difference(gcc_node_usernames,
                                          chef_node_usernames)
                for delete in delusers:
                    logger.info("Deleted user: %s" % (delete))
                    user = self.db.nodes.find_one({
                        'name':
                        delete,
                        'type':
                        'user',
                        'path':
                        get_filter_in_domain(computer)
                    })
                    computers = user['computers'] if user else []
                    if computer['_id'] in computers:
                        users_remove_policies.append(deepcopy(user))
                        computers.remove(computer['_id'])
                        self.db.nodes.update(
                            {'_id': user['_id']},
                            {'$set': {
                                'computers': computers
                            }})

                for user in users_recalculate_policies:
                    apply_policies_to_user(self.db.nodes, user, auth_user)

                for user in users_remove_policies:
                    remove_policies_of_computer(user, computer, auth_user)
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 [email protected] --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)
        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)
        except ChefServerError, 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)

        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
    def command(self):
        # Initialization
        sanitized = False
        computers = set()
        self.api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, False, self.settings.get('chef.version'))

        self.auth_user = self.db.adminusers.find_one({'username': self.options.chef_username})
        if self.auth_user is None:
            logger.error('The administrator user must exist in MongoDB')
            sys.exit(1)

        self.db = self.pyramid.db
        
        # Get local_admin_users_res (Local Administrators) policy
        logger.info('Getting Local Administrators (local_admin_users_res) policy ...')
        policy   = self.db.policies.find_one({'slug':'local_admin_users_res'})
        schema   = policy['schema']
        policyId = policy['_id']
        
        logger.info('schema   = %s'%str(schema))
        logger.info('Id.policy = %s'%str(policyId))

        # Searching nodes with the Local Administrators policy
        # Query Fields of an Embedded Document (Mongo documentation)
        # Example:
        # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}})
        logger.info('Searching nodes with the Local Administrators policy...')
        field = 'policies.' + str(policyId)
        filters  = {field:{'$exists':True}}
        nodes = self.db.nodes.find(filters)
  
        # Validating data and, where appropiate, fixing
        for node in nodes:
            instance = node['policies'][unicode(policyId)]

            logger.info('Node name = %s, _id = %s'%(node['name'],str(node['_id'])))
            logger.info('Instance before validate method: %s'%str(instance))
            while True:
                try:
                    validate(instance, schema)
                    break
                except ValidationError as e: 
                     logger.warning('Validation error on instance = %s'%str(e.message))
                     # Sanitize instance
                     self.sanitize(e, instance)
                     sanitized = True

            if sanitized:
                # Setting false sanitized for next iteration
                sanitized = False
                logger.info('Sanitized instance: %s'%str(instance))

                # Update mongo
                self.db.nodes.update({'_id': node['_id']},{'$set':{field:instance}})

                # Affected nodes
                if node['type'] == 'ou':
                    result = list(self.db.nodes.find({'path': get_filter_nodes_belonging_ou(node['_id']),'type': 'computer'},{'_id':1}))
                    logger.info('OU computers = %s'%str(result))
                elif node['type'] == 'group':
                    result = list(self.db.nodes.find({'_id':{'$in':node['members']},'type':'computer'},{'_id':1}))
                    logger.info('GROUP computers = %s'%str(result))
                elif node['type'] == 'computer':
                    result = [node]
                    logger.info('COMPUTER computers = %s'%str(result))

                [computers.add(str(n['_id'])) for n in result]


        # Removing unused local_admin_remove_list attribute in chef nodes
        for node_id in ChefNode.list():
            node = ChefNode(node_id, self.api)
            logger.info('Checking node: %s'%(node_id))
            attr_dotted = policy['path'] + '.local_admin_remove_list'
            logger.info('Atttribute dotted path: %s'%(attr_dotted))
            if node.attributes.has_dotted(attr_dotted):
                logger.info("Remove 'local_admin_remove_list' attribute!")
                try:
                    logger.info("node.attributes = %s" % str(node.attributes['gecos_ws_mgmt']['misc_mgmt']['local_admin_users_res'].to_dict()))
                    delete_dotted(node.attributes, attr_dotted)
                    node.save()
                except:
                    logger.warn("Problem deleting local_admin_remove_list value from node: %s"%(node_id))
                    logger.warn("You may be trying to delete a default attribute instead normal attribute: %s"%(node_id))

        for computer in computers:
            logger.info('computer = %s'%str(computer))
            computer = self.db.nodes.find_one({'_id': ObjectId(computer)})
            apply_policies_to_computer(self.db.nodes, computer, self.auth_user, api=self.api, initialize=False, use_celery=False)
                   
        logger.info('Finished.')
    def command(self):
        # Initialization
        logger.info("MIGRATION SCRIPT FOR FILES LIST POLICY")
        logger.info("######################################")

        # Disabling InsecureRequestWarning Unverified HTTPS request
        requests.packages.urllib3.disable_warnings()

        sanitized = False
        computers = set()                 
        self.api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, False, self.settings.get('chef.version'))

        self.auth_user = self.db.adminusers.find_one({'username': self.options.chef_username})
        if self.auth_user is None:
            logger.error('The administrator user must exist in MongoDB')
            sys.exit(1)

        self.db = self.pyramid.db
        
        # Get local_file (File list) policy
        logger.info('Getting policy schema (local_file_res) ...')
        policy   = self.db.policies.find_one({'slug':'local_file_res'})
        schema   = policy['schema']
        policyId = policy['_id']
        
        logger.info('schema   = %s'%str(schema))
        logger.debug('policyId = %s'%str(policyId))

        # Searching nodes with the File List policy
        # Query Fields of an Embedded Document (Mongo documentation)
        # Example:
        # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}})
        logger.info('Searching for nodes with applied policy...')
        field = 'policies.' + str(policyId)
        filters  = {field:{'$exists':True}}
        nodes = self.db.nodes.find(filters)
  
        # Validating data and, where appropiate, fixing
        for node in nodes:
            instance = node['policies'][unicode(policyId)]
            logger.debug("node = %s" % str(node))

            logger.info('-----------------------------------------------')
            logger.info('Node name = %s, mongo_id = %s'%(node['name'],str(node['_id'])))
            logger.info('Instance of the policy on the node: %s'%str(instance))
            while True:
                try:
                    validate(instance, schema)
                    break
                except ValidationError as e:
                    logger.warn('Validation error on instance: instance = %s'%str(instance))
                    logger.warn('Validation error on instance: message error = %s'%str(e.message))
                    # Sanitize instance
                    self.sanitize(e, instance)
                    sanitized = True

            if sanitized:
                # Setting false sanitized for next iteration
                sanitized = False
                logger.info('Sanitized instance of the policy on the node AFTER calling the validate method: %s'%str(instance))

                # Update mongo
                logger.info('Updating instance in database (mongo) ...')
                self.db.nodes.update({'_id': node['_id']},{'$set':{field:instance}})

                logger.info('Recalculating policies in the node.')

                # Affected nodes
                if node['type'] == 'ou':
                    result = list(self.db.nodes.find({'path': get_filter_nodes_belonging_ou(node['_id']),'type': 'computer'},{'_id':1}))
                    logger.info('OU computers = %s'%str(result))
                elif node['type'] == 'group':
                    result = list(self.db.nodes.find({'_id':{'$in':node['members']},'type':'computer'},{'_id':1}))
                    logger.info('GROUP computers = %s'%str(result))
                elif node['type'] == 'computer':
                    result = [node]
                    logger.info('COMPUTER computers = %s'%str(result))

                [computers.add(str(n['_id'])) for n in result]

        for computer in computers:
            logger.info('Applying policies to COMPUTER. For more information, see "gecosccui-celery.log" file')
            computer = self.db.nodes.find_one({'_id': ObjectId(computer)})
            apply_policies_to_computer(self.db.nodes, computer, self.auth_user, api=self.api, initialize=False, use_celery=True)

        # Removing unused attributes (copy_files, delete_files) in chef nodes
        logger.info('\n')
        attrs = ["%s.copy_files" % (policy['path']), "%s.delete_files" % (policy['path'])]
        logger.info('Removing unused attributes %s in chef nodes ...' % attrs)
        logger.info('\n')        
        
        for node_id in ChefNode.list():
            node = ChefNode(node_id, self.api)
            logger.info('Checking node: %s'%(node_id))
            
            for attr in attrs:
                try:
                    if node.attributes.has_dotted(attr):
                        logger.warn("Remove %s attribute!" % attr)
                        delete_dotted(node.attributes, attr)

                    node.save()

                except:
                    logger.warn("Problem deleting attribute %s value from node: %s"%(attr, node_id))
                    logger.warn("You may be trying to delete a default attribute instead normal attribute: %s"%(node_id))

        logger.info('Finished.')
Example #19
0
    def command(self):
        # Initialization
        logger.info("MIGRATION SCRIPT FOR FILES LIST POLICY")
        logger.info("######################################")

        # Disabling InsecureRequestWarning Unverified HTTPS request
        requests.packages.urllib3.disable_warnings()

        sanitized = False
        computers = set()
        self.api = _get_chef_api(self.settings.get('chef.url'),
                                 toChefUsername(self.options.chef_username),
                                 self.options.chef_pem, False,
                                 self.settings.get('chef.version'))

        self.auth_user = self.db.adminusers.find_one(
            {'username': self.options.chef_username})
        if self.auth_user is None:
            logger.error('The administrator user must exist in MongoDB')
            sys.exit(1)

        self.db = self.pyramid.db

        # Get local_file (File list) policy
        logger.info('Getting policy schema (local_file_res) ...')
        policy = self.db.policies.find_one({'slug': 'local_file_res'})
        schema = policy['schema']
        policyId = policy['_id']

        logger.info('schema   = %s' % str(schema))
        logger.debug('policyId = %s' % str(policyId))

        # Searching nodes with the File List policy
        # Query Fields of an Embedded Document (Mongo documentation)
        # Example:
        # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}})
        logger.info('Searching for nodes with applied policy...')
        field = 'policies.' + str(policyId)
        filters = {field: {'$exists': True}}
        nodes = self.db.nodes.find(filters)

        # Validating data and, where appropiate, fixing
        for node in nodes:
            instance = node['policies'][unicode(policyId)]
            logger.debug("node = %s" % str(node))

            logger.info('-----------------------------------------------')
            logger.info('Node name = %s, mongo_id = %s' %
                        (node['name'], str(node['_id'])))
            logger.info('Instance of the policy on the node: %s' %
                        str(instance))
            while True:
                try:
                    validate(instance, schema)
                    break
                except ValidationError as e:
                    logger.warn('Validation error on instance: instance = %s' %
                                str(instance))
                    logger.warn(
                        'Validation error on instance: message error = %s' %
                        str(e.message))
                    # Sanitize instance
                    self.sanitize(e, instance)
                    sanitized = True

            if sanitized:
                # Setting false sanitized for next iteration
                sanitized = False
                logger.info(
                    'Sanitized instance of the policy on the node AFTER calling the validate method: %s'
                    % str(instance))

                # Update mongo
                logger.info('Updating instance in database (mongo) ...')
                self.db.nodes.update({'_id': node['_id']},
                                     {'$set': {
                                         field: instance
                                     }})

                logger.info('Recalculating policies in the node.')

                # Affected nodes
                if node['type'] == 'ou':
                    result = list(
                        self.db.nodes.find(
                            {
                                'path': get_filter_nodes_belonging_ou(
                                    node['_id']),
                                'type': 'computer'
                            }, {'_id': 1}))
                    logger.info('OU computers = %s' % str(result))
                elif node['type'] == 'group':
                    result = list(
                        self.db.nodes.find(
                            {
                                '_id': {
                                    '$in': node['members']
                                },
                                'type': 'computer'
                            }, {'_id': 1}))
                    logger.info('GROUP computers = %s' % str(result))
                elif node['type'] == 'computer':
                    result = [node]
                    logger.info('COMPUTER computers = %s' % str(result))

                [computers.add(str(n['_id'])) for n in result]

        for computer in computers:
            logger.info(
                'Applying policies to COMPUTER. For more information, see "gecosccui-celery.log" file'
            )
            computer = self.db.nodes.find_one({'_id': ObjectId(computer)})
            apply_policies_to_computer(self.db.nodes,
                                       computer,
                                       self.auth_user,
                                       api=self.api,
                                       initialize=False,
                                       use_celery=True)

        # Removing unused attributes (copy_files, delete_files) in chef nodes
        logger.info('\n')
        attrs = [
            "%s.copy_files" % (policy['path']),
            "%s.delete_files" % (policy['path'])
        ]
        logger.info('Removing unused attributes %s in chef nodes ...' % attrs)
        logger.info('\n')

        for node_id in ChefNode.list():
            node = ChefNode(node_id, self.api)
            logger.info('Checking node: %s' % (node_id))

            for attr in attrs:
                try:
                    if node.attributes.has_dotted(attr):
                        logger.warn("Remove %s attribute!" % attr)
                        delete_dotted(node.attributes, attr)

                    node.save()

                except:
                    logger.warn(
                        "Problem deleting attribute %s value from node: %s" %
                        (attr, node_id))
                    logger.warn(
                        "You may be trying to delete a default attribute instead normal attribute: %s"
                        % (node_id))

        logger.info('Finished.')
    def command(self):
        # Initialization
        self.api = _get_chef_api(self.settings.get('chef.url'),
                                 toChefUsername(self.options.chef_username),
                                 self.options.chef_pem, False,
                                 self.settings.get('chef.version'))

        self.auth_user = self.db.adminusers.find_one(
            {'username': self.options.chef_username})
        if self.auth_user is None:
            logger.error('The administrator user must exist in MongoDB')
            return

        self.db = self.pyramid.db
        ous = []
        groups = []
        computers = []

        # Get packages policy ID
        packages_policy = self.db.policies.find_one({"slug": "package_res"})
        if packages_policy is None:
            logger.error('Can\'t detect "package_res" policy!')
            return

        if 'pkgs_to_remove' in packages_policy["schema"]["properties"]:
            logger.error(
                "The 'package_res' policy in the system is deprecated, please update to new package policy!"
            )
            return

        logger.info('Packages policy ID: %s' % (str(packages_policy['_id'])))

        # Get all nodes with old package policy data
        logger.info('Getting all nodes with old package policy data...')
        path_to_find = "policies.%s.pkgs_to_remove" % (str(
            packages_policy['_id']))
        old_policy_nodes = self.db.nodes.find({
            '$query': {
                path_to_find: {
                    '$exists': True
                }
            },
            '$orderby': {
                "path": 1
            }
        })

        updated_nodes = []
        for node in old_policy_nodes:
            logger.info('Updating node %s ...' % (str(node['_id'])))
            updated_nodes.append(str(node['_id']))

            logger.debug('Packages to add: %s' % (str(node['policies'][str(
                packages_policy['_id'])]['package_list'])))
            logger.debug('Packages to remove: %s' % (str(node['policies'][str(
                packages_policy['_id'])]['pkgs_to_remove'])))

            # Join the lists
            package_list = []
            for package_name in node['policies'][str(
                    packages_policy['_id'])]['package_list']:
                package_list.append({
                    'name': package_name,
                    'version': 'current',
                    'action': 'add'
                })

            for package_name in node['policies'][str(
                    packages_policy['_id'])]['pkgs_to_remove']:
                package_list.append({
                    'name': package_name,
                    'version': 'current',
                    'action': 'remove'
                })

            if 'pkgs_to_remove' in node['policies'][str(
                    packages_policy['_id'])]:
                del node['policies'][str(
                    packages_policy['_id'])]['pkgs_to_remove']

            node['policies'][str(
                packages_policy['_id'])]['package_list'] = package_list

            # Update policies
            self.db.nodes.update({'_id': node['_id']},
                                 {'$set': {
                                     'policies': node['policies']
                                 }})
            logger.debug('Joined list: %s' % (str(node['policies'][str(
                packages_policy['_id'])]['package_list'])))

            if node['type'] == 'ou':
                ous.append(node)
            elif node['type'] == 'group':
                groups.append(node)
            elif node['type'] == 'computer':
                computers.append(node)

        logger.info('%s nodes were updated!' % (len(updated_nodes)))

        # We only go through the highest level OUs.
        # Therefore, we eliminate intermediate OUs and
        # then do not recalculate the policies
        # for the same node several times.
        for ou in ous:
            parents = [
                ObjectId(oid) for oid in ou['path'].split(',') if oid != 'root'
            ]
            if any(o['_id'] in parents for o in ous):
                ous.remove(ou)

        # Users that are not under an OU or GROUP that have the migrated policy
        for computer in computers:
            parents = [
                ObjectId(oid) for oid in computer['path'].split(',')
                if oid != 'root'
            ]
            if any(o['_id'] in parents for o in ous):
                computers.remove(computer)
            elif any(computer['_id'] in group['members'] for group in groups):
                computers.remove(computer)

        # Recalculating policies for OU
        for ou in ous:
            old = deepcopy(ou)
            del old["policies"][str(packages_policy['_id'])]
            object_changed(self.auth_user, 'ou', ou, old)

        # Recalculating policies for GROUP
        for group in groups:
            old = deepcopy(group)
            del old["policies"][str(packages_policy['_id'])]
            object_changed(self.auth_user, 'group', group, old)

        # Recalculating policies for USER
        for computer in computers:
            old = deepcopy(computer)
            del old["policies"][str(packages_policy['_id'])]
            object_changed(self.auth_user, 'computer', computer, old)

        # Recalculate policies for Chef nodes
        for node_id in ChefNode.list():
            node = ChefNode(node_id, self.api)
            logger.info('Checking node: %s' % (node_id))
            if ("gecos_ws_mgmt" in node.attributes) and (
                    "software_mgmt" in node.attributes["gecos_ws_mgmt"]) and (
                        "package_res"
                        in node.attributes["gecos_ws_mgmt"]["software_mgmt"]):
                if "pkgs_to_remove" in node.attributes["gecos_ws_mgmt"][
                        "software_mgmt"]["package_res"]:
                    logger.debug(
                        "Chef node %s contains a pkgs_to_remove value!" %
                        (node_id))
                    # Remove pkgs_to_remove from mongodb node
                    logger.info("Remove 'pkgs_to_remove' attribute!")
                    try:
                        del node.attributes["gecos_ws_mgmt"]["software_mgmt"][
                            "package_res"]["pkgs_to_remove"]
                        node.save()
                    except:
                        logger.warn(
                            "Problem deleting pkgs_to_remove value from node: %s"
                            % (node_id))

                if not "package_list" in node.attributes["gecos_ws_mgmt"][
                        "software_mgmt"]["package_res"]:
                    logger.error(
                        "Chef node %s doesn\'t contains a package_list value!"
                        % (node_id))
                    continue

                package_list = node.attributes["gecos_ws_mgmt"][
                    "software_mgmt"]["package_res"]["package_list"]
                for element in package_list:
                    if not 'action' in element:
                        logger.debug(
                            'Chef node: %s doesn\'t have an action value in package_res! (package_list:%s)'
                            % (node_id, str(package_list)))
                        break

        # Final check
        bad_nodes = Search('node',
                           "pkgs_to_remove:*",
                           rows=1000,
                           start=0,
                           api=self.api)
        for node in bad_nodes:
            logger.warn('Detected bad node: %s' % (node.object.name))
            gecos_node = self.db.nodes.find_one(
                {"node_chef_id": node.object.name})
            if gecos_node is None:
                logger.warn('Can\'t find node in MongoDB for: %s' %
                            (node.object.name))
            else:
                logger.warn(
                    'For an unknown reason a computer called %s wasn\'t updated!'
                    % (gecos_node['name']))

        logger.info('END ;)')
    def command(self):
        # Initialization
        logger.info("MIGRATION SCRIPT FOR USER_APPS_AUTOSTART POLICY")
        logger.info("###############################################")

        # Disabling InsecureRequestWarning Unverified HTTPS request
        requests.packages.urllib3.disable_warnings()

        sanitized = False
        ous = []
        groups = []
        users = []
        self.api = _get_chef_api(self.settings.get('chef.url'),
                                 toChefUsername(self.options.chef_username),
                                 self.options.chef_pem, False,
                                 self.settings.get('chef.version'))

        self.auth_user = self.db.adminusers.find_one(
            {'username': self.options.chef_username})
        if self.auth_user is None:
            logger.error('The administrator user must exist in MongoDB')
            sys.exit(1)

        self.db = self.pyramid.db

        # Get local_users (Users) policy
        logger.info('Getting policy schema (user_apps_autostart_res) ...')
        policy = self.db.policies.find_one({'slug': 'user_apps_autostart_res'})
        schema = policy['schema']
        policyId = policy['_id']

        logger.info('schema   = %s' % str(schema))
        logger.debug('policyId = %s' % str(policyId))

        # Searching nodes with the Local Administrators policy
        # Query Fields of an Embedded Document (Mongo documentation)
        # Example:
        # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}})
        logger.info('Searching for nodes with applied policy...')
        field = 'policies.' + str(policyId)
        filters = {field: {'$exists': True}}
        nodes = self.db.nodes.find(filters)

        # Validating data and, where appropiate, fixing
        for node in nodes:
            instance = node['policies'][unicode(policyId)]
            logger.info("node = %s" % str(node))

            logger.info('-----------------------------------------------')
            logger.info('Node name = %s, mongo_id = %s' %
                        (node['name'], str(node['_id'])))
            logger.info('Instance of the policy on the node: %s' %
                        str(instance))
            while True:
                try:
                    validate(instance, schema)
                    break
                except ValidationError as e:
                    logger.warn('Validation error on instance = %s' %
                                str(e.message))
                    # Sanitize instance
                    self.sanitize(e, instance)
                    sanitized = True

            if sanitized:
                # Setting false sanitized for next iteration
                sanitized = False
                logger.info(
                    'Sanitized instance of the policy on the node AFTER calling the validate method: %s'
                    % str(instance))

                # Update mongo
                logger.info('Updating instance in database (mongo) ...')
                self.db.nodes.update({'_id': node['_id']},
                                     {'$set': {
                                         field: instance
                                     }})

                logger.info('Recalculating policies in the node.')
                # Affected nodes
                if node['type'] == 'ou':
                    ous.append(node)
                elif node['type'] == 'group':
                    groups.append(node)
                elif node['type'] == 'user':
                    users.append(node)

        # We only go through the highest level OUs.
        # Therefore, we eliminate intermediate OUs and
        # then do not recalculate the policies
        # for the same node several times.
        for ou in ous:
            parents = [
                ObjectId(oid) for oid in ou['path'].split(',') if oid != 'root'
            ]
            if any(o['_id'] in parents for o in ous):
                ous.remove(ou)

        # Users that are not under an OU or GROUP that have the migrated policy
        for user in users:
            parents = [
                ObjectId(oid) for oid in user['path'].split(',')
                if oid != 'root'
            ]
            if any(o['_id'] in parents for o in ous):
                users.remove(user)
            elif any(user['_id'] in group['members'] for group in groups):
                users.remove(user)

        # Recalculating policies for OU
        for ou in ous:
            old = deepcopy(ou)
            del old["policies"][str(policyId)]
            object_changed(self.auth_user, 'ou', ou, old)

        # Recalculating policies for GROUP
        for group in groups:
            old = deepcopy(group)
            del old["policies"][str(policyId)]
            object_changed(self.auth_user, 'group', group, old)

        # Recalculating policies for USER
        for user in users:
            old = deepcopy(user)
            del old["policies"][str(policyId)]
            object_changed(self.auth_user, 'user', user, old)

        # Removing unused desktops_to_remove attribute in chef nodes
        logger.info('\n')
        logger.info(
            'Removing unused desktops_to_remove attribute in chef nodes ...')
        for node_id in ChefNode.list():
            node = ChefNode(node_id, self.api)
            logger.info('Checking node: %s' % (node_id))
            field_chef = '%s.users' % policy['path']
            users = node.attributes.get_dotted(
                field_chef) if node.attributes.has_dotted(field_chef) else []
            for user in users:
                logger.debug("user = %s" % (user))
                attr_delete_path = '%s.%s.desktops_to_remove' % (field_chef,
                                                                 user)
                logger.debug('Atttribute dotted path: %s' % (attr_delete_path))
                if node.attributes.has_dotted(attr_delete_path):
                    logger.warn(
                        "Remove 'desktops_to_remove' attribute! for user %s" %
                        (user))
                    try:
                        delete_dotted(node.attributes, attr_delete_path)
                        node.save()
                    except:
                        logger.warn(
                            "Problem deleting desktops_to_remove value from node: %s"
                            % (node_id))
                        logger.warn(
                            "You may be trying to delete a default attribute instead normal attribute: %s"
                            % (node_id))

        logger.info('Finished.')
Example #22
0
    def command(self):
        api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, False, self.settings.get('chef.version'))
                            
        print '============ CHECKING ADMINISTRATOR USERS ============='                  
        # Check if all the GECOS CC administrators
        # are properly created in Chef 12
        admin_users = self.pyramid.userdb.list_users()
        for admin_user in admin_users:
            print 'Checking admin user: %s'%(admin_user['username'])
            
            # The email must be unique
            users_with_email = self.pyramid.userdb.list_users({'email': admin_user['email']})
            if users_with_email.count() > 1:
                print "ERROR: more than one user with this email: %s"%(admin_user['email'])

            # Get the Chef user
            chef_user = None
            try:
                chef_user = api['/users/%s' % toChefUsername(admin_user['username'])]
            except ChefServerNotFoundError:
                pass            
                            
            if chef_user is None:
                # No chef user found
                print "WARNING: No Chef user found. We will try to create it!"
                
                chef_password = password_generator()
                try:
                    create_chef_admin_user(api, self.settings, toChefUsername(admin_user['username']), chef_password, admin_user['email'])
                except ChefServerError, e:
                    print "ERROR: User not created in chef, error was: %s" % e
                    print "(Check /opt/opscode/embedded/service/opscode-erchef/log/requests.log* for more info)"
                    sys.exit(1)                
                            
                chef_user = api['/users/%s' % toChefUsername(admin_user['username'])]

            # Check the email of the chef user
            if chef_user['email'] != admin_user['email']:
                print "WARNING: The chef user email and the GECOS CC user email doesn't match!"
                print "Try to change the chef user email!"
                chef_user['email'] = admin_user['email']
                api.api_request('PUT', '/users/%s'%(toChefUsername(admin_user['username'])), data=chef_user)                
            
            # Check if the administrator belongs to the "admins" group in the "default" organization
            admins_group = None
            try:
                admins_group = api['/organizations/default/groups/admins']
            except ChefServerNotFoundError:
                pass             
                
            if not toChefUsername(admin_user['username']) in admins_group['users']:
                print "WARNING: GECOS administrator is not a chef administrator for the default organization. We will try to change this!"
                
                # Check if exists an association request for this user
                assoc_requests = None
                try:
                    assoc_requests = api['/organizations/default/association_requests']
                except ChefServerNotFoundError:
                    pass                    
                
                association_id = None
                for req in assoc_requests:
                    if req["username"] == toChefUsername(admin_user['username']):
                        association_id = req["id"]
                
                if association_id is None:
                    # Set an association request for the user in that organization
                    try:
                        data = {"user": toChefUsername(admin_user['username'])}
                        response = api.api_request('POST', '/organizations/default/association_requests', data=data) 
                        association_id = response["uri"].split("/")[-1]
                    except ChefServerError:
                        # Association already exists?
                        pass                    

                if association_id is not None:
                    # Accept the association request
                    api.api_request('PUT', '/users/%s/association_requests/%s'%(toChefUsername(admin_user['username']), association_id),  data={ "response": 'accept' }) 

                # Add the user to the group
                admins_group['users'].append(toChefUsername(admin_user['username']))
                api.api_request('PUT', '/organizations/default/groups/admins', data={ "groupname": admins_group["groupname"], 
                    "actors": {
                        "users": admins_group['users'],
                        "groups": admins_group["groups"]
                    }
                    }) 
Example #23
0
    def command(self):
        from gecoscc.api.chef_status import USERS_OLD, USERS_OHAI
        # Initialization
        self.api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, False, self.settings.get('chef.version'))

        self.db = self.pyramid.db

        # Check administrator user
        auth_user = self.db.adminusers.find_one({'username': self.options.chef_username})
        if auth_user is None:
            logger.error('The administrator user must exist in MongoDB')
            sys.exit(1)

        # Recorriendo todos los nodos 
        for node_id in ChefNode.list():
            node = ChefNode(node_id, self.api)
            logger.info('Checking node: %s'%(node_id))
            
            try:
                if node.attributes.get_dotted(USERS_OLD):
                    delete_dotted(node.attributes, USERS_OLD)
                    node.save()
            except KeyError:
                logger.warn("Not found attribute: %s"%(USERS_OLD))
            except:
                logger.warn("Problem deleting users_old attribute from node: %s"%(node_id))

            # Updating users list    
            computer = self.db.nodes.find_one({'node_chef_id': node_id, 'type':'computer'})
            if not computer:
                logger.error('This node does not exist (mongodb)')
                continue
 
            chef_node_usernames = set([d['username'] for d in  node.attributes.get_dotted(USERS_OHAI)])
            gcc_node_usernames  = set([d['name'] for d in self.db.nodes.find({
                                       'type':'user',
                                       'computers': {'$in': [computer['_id']]}
                                    },
                                    {'_id':0, 'name':1})
                                 ])


            users_recalculate_policies = []
            users_remove_policies = []

            # Users added/removed ?
            if set.symmetric_difference(chef_node_usernames, gcc_node_usernames):
                logger.info("Users added/removed found.")

                # Add users or vinculate user to computer if already exists
                addusers = set.difference(chef_node_usernames, gcc_node_usernames)
                for add in addusers:
                    logger.info("Added user: %s"%(add))
                    user = self.db.nodes.find_one({'name': add, 'type': 'user', 'path': get_filter_in_domain(computer)})

                    if not user:
                        user_model = User()
                        user = user_model.serialize({'name': add,
                                                     'path': computer.get('path', ''),
                                                     'type': 'user',
                                                     'lock': computer.get('lock', ''),
                                                     'source': computer.get('source', '')})

                        user = update_computers_of_user(self.db, user, self.api)

                        del user['_id']
                        user_id = self.db.nodes.insert(user)
                        user = self.db.nodes.find_one({'_id': user_id})
                        users_recalculate_policies.append(user)

                    else:
                        computers = user.get('computers', [])
                        if computer['_id'] not in computers:
                            computers.append(computer['_id'])
                            self.db.nodes.update({'_id': user['_id']}, {'$set': {'computers': computers}})
                            users_recalculate_policies.append(user)
                            add_computer_to_user(computer['_id'], user['_id'])

                # Removed users
                delusers = set.difference(gcc_node_usernames, chef_node_usernames)
                for delete in delusers:
                    logger.info("Deleted user: %s"%(delete))
                    user = self.db.nodes.find_one({'name': delete,
                                                   'type': 'user',
                                                   'path': get_filter_in_domain(computer)})
                    computers = user['computers'] if user else []
                    if computer['_id'] in computers:
                        users_remove_policies.append(deepcopy(user))
                        computers.remove(computer['_id'])
                        self.db.nodes.update({'_id': user['_id']}, {'$set': {'computers': computers}})

                for user in users_recalculate_policies:
                    apply_policies_to_user(self.db.nodes, user, auth_user)

                for user in users_remove_policies:
                    remove_policies_of_computer(user, computer, auth_user)
 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')
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 [email protected] --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, 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 /opt/opscode/bin/chef-server-ctl does not exists in the system
                # Probably Chef Server and GECOS Control Center are installed in different machines
                print "NOTICE: Please remember to grant server admin permissions to this user by executing the following command in Chef 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, 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, e:
                print "User not added to default organization's admins group in chef, error was: %s" % e
                sys.exit(1)
    def command(self):
        # Initialization
        sanitized = False
        computers = set()
        self.api = _get_chef_api(self.settings.get('chef.url'),
                                 toChefUsername(self.options.chef_username),
                                 self.options.chef_pem, False,
                                 self.settings.get('chef.version'))

        self.auth_user = self.db.adminusers.find_one(
            {'username': self.options.chef_username})
        if self.auth_user is None:
            logger.error('The administrator user must exist in MongoDB')
            sys.exit(1)

        self.db = self.pyramid.db

        # Get local_users (Users) policy
        logger.info('Getting Users (local_users_res) policy ...')
        policy = self.db.policies.find_one({'name': 'Users'})
        schema = policy['schema']
        policyId = policy['_id']

        logger.debug('schema   = %s' % str(schema))
        logger.debug('Id.policy = %s' % str(policyId))

        # Searching nodes with the Users policy
        # Query Fields of an Embedded Document (Mongo documentation)
        # Example:
        # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}})
        logger.info('Searching nodes with the Users policy...')
        field = 'policies.' + str(policyId)
        filters = {field: {'$exists': True}}
        nodes = self.db.nodes.find(filters).sort([('path', 1), ('name', 1)])

        # Validating data and, where appropiate, fixing
        for node in nodes:
            instance = node['policies'][unicode(policyId)]

            logger.info('Node name = %s, _id = %s' %
                        (node['name'], str(node['_id'])))
            logger.info('Instance before validate method: %s' % str(instance))
            while True:
                try:
                    validate(instance, schema)
                    break
                except ValidationError as e:
                    logger.warning('Validation error on instance = %s' %
                                   str(e.message))
                    # Sanitize instance
                    self.sanitize(e, instance)
                    sanitized = True

            if sanitized:
                # Setting false sanitized for next iteration
                sanitized = False
                logger.info('Sanitized instance: %s' % str(instance))

                # Update mongo
                self.db.nodes.update({'_id': node['_id']},
                                     {'$set': {
                                         field: instance
                                     }})

                # Affected nodes
                if node['type'] == 'ou':
                    result = list(
                        self.db.nodes.find(
                            {
                                'path': get_filter_nodes_belonging_ou(
                                    node['_id']),
                                'type': 'computer'
                            }, {'_id': 1}))
                    logger.info('OU computers = %s' % str(result))
                elif node['type'] == 'group':
                    result = list(
                        self.db.nodes.find(
                            {
                                '_id': {
                                    '$in': node['members']
                                },
                                'type': 'computer'
                            }, {'_id': 1}))
                    logger.info('GROUP computers = %s' % str(result))
                elif node['type'] == 'computer':
                    result = [node]
                    logger.info('COMPUTER computers = %s' % str(result))

                [computers.add(str(n['_id'])) for n in result]

        for computer in computers:
            logger.info('computer = %s' % str(computer))
            computer = self.db.nodes.find_one({'_id': ObjectId(computer)})
            apply_policies_to_computer(self.db.nodes,
                                       computer,
                                       self.auth_user,
                                       api=self.api,
                                       initialize=False,
                                       use_celery=False)

        logger.info('Finished.')
    def command(self):
        # Initialization
        logger.info("MIGRATION SCRIPT FOR USER_LAUNCHERS POLICY")
        logger.info("###############################################")

        # Disabling InsecureRequestWarning Unverified HTTPS request
        requests.packages.urllib3.disable_warnings()

        sanitized = False
        ous = []
        groups = []
        users = []
        self.api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, False, self.settings.get('chef.version'))

        self.auth_user = self.db.adminusers.find_one({'username': self.options.chef_username})
        if self.auth_user is None:
            logger.error('The administrator user must exist in MongoDB')
            sys.exit(1)

        self.db = self.pyramid.db
        
        # Get local_users (Users) policy
        logger.info('Getting policy schema (user_launchers_res) ...')
        policy   = self.db.policies.find_one({'slug':'user_launchers_res'})
        schema   = policy['schema']
        policyId = policy['_id']
        
        logger.info('schema   = %s'%str(schema))
        logger.debug('policyId = %s'%str(policyId))

        # Searching nodes with the Local Administrators policy
        # Query Fields of an Embedded Document (Mongo documentation)
        # Example:
        # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}})
        logger.info('Searching for nodes with applied policy...')
        field = 'policies.' + str(policyId)
        filters  = {field:{'$exists':True}}
        nodes = self.db.nodes.find(filters)
  
        # Validating data and, where appropiate, fixing
        for node in nodes:
            instance = node['policies'][unicode(policyId)]
            logger.info("node = %s" % str(node))

            logger.info('-----------------------------------------------')
            logger.info('Node name = %s, mongo_id = %s'%(node['name'],str(node['_id'])))
            logger.info('Instance of the policy on the node: %s'%str(instance))
            while True:
                try:
                    validate(instance, schema)
                    break
                except ValidationError as e: 
                     logger.warn('Validation error on instance = %s'%str(e.message))
                     # Sanitize instance
                     self.sanitize(e, instance)
                     sanitized = True

            if sanitized:
                # Setting false sanitized for next iteration
                sanitized = False
                logger.info('Sanitized instance of the policy on the node AFTER calling the validate method: %s'%str(instance))

                # Update mongo
                logger.info('Updating instance in database (mongo) ...')
                self.db.nodes.update({'_id': node['_id']},{'$set':{field:instance}})

                logger.info('Recalculating policies in the node.')
                # Affected nodes
                if   node['type'] == 'ou':
                    ous.append(node)
                elif node['type'] == 'group':
                    groups.append(node)
                elif node['type'] == 'user':
                    users.append(node)

        # We only go through the highest level OUs. 
        # Therefore, we eliminate intermediate OUs and 
        # then do not recalculate the policies
        # for the same node several times.
        for ou in ous:
            parents = [ObjectId(oid) for oid in ou['path'].split(',') if oid != 'root']
            if any(o['_id'] in parents for o in ous):
                ous.remove(ou)

        # Users that are not under an OU or GROUP that have the migrated policy
        for user in users:
            parents = [ObjectId(oid) for oid in user['path'].split(',') if oid != 'root'] 
            if any(o['_id'] in parents for o in ous):
                users.remove(user)
            elif any(user['_id'] in group['members'] for group in groups):
                users.remove(user)

        # Recalculating policies for OU
        for ou in ous: 
            old = deepcopy(ou)
            del old["policies"][str(policyId)]
            object_changed(self.auth_user, 'ou', ou, old)

        # Recalculating policies for GROUP
        for group in groups:
            old = deepcopy(group)
            del old["policies"][str(policyId)]
            object_changed(self.auth_user, 'group', group, old)

        # Recalculating policies for USER
        for user in users:
            old = deepcopy(user)
            del old["policies"][str(policyId)]
            object_changed(self.auth_user, 'user', user, old)

        logger.info('Finished.')
Example #28
0
    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)
Example #29
0
    def command(self):
        # Initialization
        self.api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, False, self.settings.get('chef.version'))

        self.db = self.pyramid.db
        self.referenced_data_type = {}
        self.referenced_data_type['storage_can_view'] = 'storage'
        self.referenced_data_type['repository_can_view'] = 'repository'
        self.referenced_data_type['printer_can_view'] = 'printer'
        
        # Get gecos_ws_mgmt cookbook default data structure
        default_data_dotted_keys = {}
        default_data = self.get_default_data(default_data_dotted_keys)
        if default_data is None:
            logger.error("Can't find default data!")
            return
        
        # Get all the policies structures
        logger.info('Getting all the policies structures from database...')
        dbpolicies = self.db.policies.find()
        self.policiesdata = {}
        self.slug_check = {}
        for policy in dbpolicies:
            logger.debug('Addig to dictionary: %s => %s'%(policy['_id'], json.dumps(policy['schema'])))
            self.policiesdata[str(policy['_id'])] = policy
            
            # Check policy slug field (must be unique)
            if policy['slug'] in self.slug_check:
                logger.error("There are more than one policy with '%s' slug!"%(policy['slug']))
            else:
                self.slug_check[policy['slug']] = policy
                
            # Check policy serialization
            try:
                logger.debug('Serialized policy: %s'%(json.dumps(Policy().serialize(policy))))
            except Exception as err:
                logger.error('Policy %s with slug %s can\'t be serialized: %s'%(policy['_id'], policy['slug'], str(err)))
                logger.warn('Possible cause: New fields in models (Colander) but the import_policies command has not yet been executed to update schema.')
                
        if self.options.clean_inheritance:
            logger.info('Cleaning inheritance field...')
            self.db.nodes.update({"inheritance": { '$exists': True }}, { '$unset': { "inheritance": {'$exist': True } }}, multi=True)
        
        logger.info('Checking tree...')
        # Look for the root of the nodes tree
        root_nodes = self.db.nodes.find({"path" : "root"})    
        for root in root_nodes:        
            self.check_node_and_subnodes(root)
        
        logger.info('Checking nodes that are outside the tree (missing OUs in the PATH)...')
        # Check node path
        nodes = self.db.nodes.find({})    
        for node in nodes:
            if not 'path' in node:
                logger.error('Node with ID: %s has no "path" attribute!'%(str(node['_id'])))                
                continue

            if not 'name' in node:
                logger.error('Node with ID: %s has no "name" attribute!'%(str(node['_id'])))                
                continue

            if not 'type' in node:
                logger.error('Node with ID: %s has no "type" attribute!'%(str(node['_id'])))                
                continue

                
            for ou_id in node['path'].split(','):
                if ou_id == 'root':
                    continue
                    
                ou = self.db.nodes.find_one({ "_id" : ObjectId(ou_id) })    
                if not ou:
                    logger.error('Can\'t find OU %s that belongs to node path (node ID: %s NAME: %s)'%(str(ou_id), str(node['_id']), node['name']))                
                    continue        
        
        logger.info('Checking chef node references...')
        # Check the references to Chef nodes
        computers = self.db.nodes.find({"type" : "computer"})    
        for computer in computers:  
            if "node_chef_id" in computer:
                # Check Chef node
                computer_node = ChefNode(computer['node_chef_id'], self.api)
                logger.info("Computer: %s Chef ID: %s"%(computer['name'], computer['node_chef_id']))
                if not computer_node.exists:
                    logger.error("No Chef node with ID %s!"%(computer['node_chef_id']))
                
            else:
                logger.error("No Chef ID in '%s' computer!"%(computer['name']))

                
        logger.info('Checking MongoDB computer references...')
        # Check the references to computer nodes
        for node_id in ChefNode.list():
            found = False
            computers = self.db.nodes.find({"node_chef_id" : node_id})    
            for computer in computers:   
                found = True
                
            computer_node = ChefNode(node_id, self.api)
            if not found:
                pclabel = "(No OHAI-GECOS data in the node)"
                try:
                    pclabel = "(pclabel = %s)"%( computer_node.attributes.get_dotted('ohai_gecos.pclabel') )
                except KeyError:
                    pass
                        
                logger.error("No computer node for Chef ID: '%s' %s!"%(node_id, pclabel))
                logger.warn("Possible cause: The node has been deleted in Gecos Control Center but not in Chef server, either because it was in use at that time or for another unknown reason.")
        
            # Check default data for chef node
            if not computer_node.default.to_dict() or not computer_node.attributes.has_dotted('gecos_ws_mgmt'):
                logger.info("FIXED: For an unknown reason Chef node: %s has no default attributes."%(node_id))
                computer_node.default = default_data
                computer_node.save()
                
            # Check "updated_by" field
            atrributes = computer_node.normal.to_dict()
            updated, updated_attributes = self.check_updated_by_field(node_id, None, atrributes)
            if updated:
                computer_node.normal = atrributes
                computer_node.save()
            
        
        logger.info('END ;)')
                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, 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
    def command(self):
        # Initialization
        sanitized = False
        computers = set()
        self.api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, False, self.settings.get('chef.version'))

        self.auth_user = self.db.adminusers.find_one({'username': self.options.chef_username})       
        if self.auth_user is None:
            logger.error('The administrator user must exist in MongoDB')
            sys.exit(1)                            

        self.db = self.pyramid.db
        
        # Get local_groups (Local groups) policy
        logger.info('Getting Local Groups (local_groups_res) policy ...')
        policy   = self.db.policies.find_one({'name':'Local groups'})
        schema   = policy['schema']
        policyId = policy['_id']
        
        logger.debug('schema   = %s'%str(schema))
        logger.debug('Id.policy = %s'%str(policyId))

        # Searching nodes with the Local Groups policy
        # Query Fields of an Embedded Document (Mongo documentation)
        # Example:
        # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}})
        logger.info('Searching nodes with the Local Groups policy...')
        field = 'policies.' + str(policyId)
        filters  = {field:{'$exists':True}}
        nodes = self.db.nodes.find(filters).sort([('path',1),('name',1)])
  
        # Validating data and, where appropiate, fixing
        for node in nodes:
            instance = node['policies'][unicode(policyId)]

            logger.info('Node name = %s, _id = %s)'%(node['name'],str(node['_id'])))
            logger.info('Instance before validate method: %s'%str(instance))
            while True:
                try:
                    validate(instance, schema)
                    break
                except ValidationError as e: 
                     logger.warning('Validation error on instance = %s'%str(e.message))
                     # Sanitize instance
                     self.sanitize(e, instance)
                     sanitized = True

            if sanitized:
                # Setting false sanitized for next iteration
                sanitized = False
                logger.info('Sanitized instance: %s'%str(instance))

                # Update mongo
                self.db.nodes.update({'_id': node['_id']},{'$set':{field:instance}})

                # Affected nodes
                if node['type'] == 'ou':
                    result = list(self.db.nodes.find({'path': get_filter_nodes_belonging_ou(node['_id']),'type': 'computer'},{'_id':1}))
                    logger.info('OU computers = %s'%str(result))
                elif node['type'] == 'group':
                    result = list(self.db.nodes.find({'_id':{'$in':node['members']},'type':'computer'},{'_id':1}))
                    logger.info('GROUP computers = %s'%str(result))
                elif node['type'] == 'computer':
                    result = [node]
                    logger.info('COMPUTER computers = %s'%str(result))

                [computers.add(str(n['_id'])) for n in result]

        for computer in computers:
            logger.info('computer = %s'%str(computer))
            computer = self.db.nodes.find_one({'_id': ObjectId(computer)})
            apply_policies_to_computer(self.db.nodes, computer, self.auth_user, api=self.api, initialize=False, use_celery=False) 

        logger.info('Finished.')
 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 command(self):
        # Initialization
        self.api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, False, self.settings.get('chef.version'))

        self.auth_user = self.db.adminusers.find_one({'username': self.options.chef_username})       
        if self.auth_user is None:
            logger.error('The administrator user must exist in MongoDB')
            return
        

        self.db = self.pyramid.db
        ous = []
        groups = []
        computers = []

        # Get packages policy ID
        packages_policy = self.db.policies.find_one({"slug": "package_res"})
        if packages_policy is None:
            logger.error('Can\'t detect "package_res" policy!')
            return
            
        if 'pkgs_to_remove' in packages_policy["schema"]["properties"]:
            logger.error("The 'package_res' policy in the system is deprecated, please update to new package policy!")
            return
        
            
        logger.info('Packages policy ID: %s'%(str(packages_policy['_id'])))
        
        # Get all nodes with old package policy data
        logger.info('Getting all nodes with old package policy data...')
        path_to_find = "policies.%s.pkgs_to_remove"%(str(packages_policy['_id']))
        old_policy_nodes = self.db.nodes.find({ '$query': {path_to_find: { '$exists': True }}, '$orderby': { "path" : 1 }})
        
        updated_nodes = []
        for node in old_policy_nodes:
            logger.info('Updating node %s ...'%(str(node['_id'])))
            updated_nodes.append(str(node['_id']))
            
            logger.debug('Packages to add: %s'%(str(node['policies'][str(packages_policy['_id'])]['package_list'])))
            logger.debug('Packages to remove: %s'%(str(node['policies'][str(packages_policy['_id'])]['pkgs_to_remove'])))
            
            # Join the lists
            package_list = []
            for package_name in node['policies'][str(packages_policy['_id'])]['package_list']:
                package_list.append({'name': package_name, 'version': 'current', 'action': 'add'})
            
            for package_name in node['policies'][str(packages_policy['_id'])]['pkgs_to_remove']:
                package_list.append({'name': package_name, 'version': 'current', 'action': 'remove'})
            
            if 'pkgs_to_remove' in node['policies'][str(packages_policy['_id'])]:
                del node['policies'][str(packages_policy['_id'])]['pkgs_to_remove']
                
            node['policies'][str(packages_policy['_id'])]['package_list'] = package_list
            
            # Update policies
            self.db.nodes.update({'_id': node['_id']}, {'$set': {'policies': node['policies']}})
            logger.debug('Joined list: %s'%(str(node['policies'][str(packages_policy['_id'])]['package_list'])))

            if   node['type'] == 'ou':
                ous.append(node)                                    
            elif node['type'] == 'group':                                             
                groups.append(node)
            elif node['type'] == 'computer':
                computers.append(node)

        logger.info('%s nodes were updated!'%(len(updated_nodes)))

        # We only go through the highest level OUs. 
        # Therefore, we eliminate intermediate OUs and 
        # then do not recalculate the policies
        # for the same node several times.
        for ou in ous:
            parents = [ObjectId(oid) for oid in ou['path'].split(',') if oid != 'root']
            if any(o['_id'] in parents for o in ous):
                ous.remove(ou)

        # Users that are not under an OU or GROUP that have the migrated policy
        for computer in computers:
            parents = [ObjectId(oid) for oid in computer['path'].split(',') if oid != 'root'] 
            if any(o['_id'] in parents for o in ous):
                computers.remove(computer)
            elif any(computer['_id'] in group['members'] for group in groups):
                computers.remove(computer)

        # Recalculating policies for OU
        for ou in ous: 
            old = deepcopy(ou)
            del old["policies"][str(packages_policy['_id'])]
            object_changed(self.auth_user, 'ou', ou, old)

        # Recalculating policies for GROUP
        for group in groups:
            old = deepcopy(group)
            del old["policies"][str(packages_policy['_id'])]
            object_changed(self.auth_user, 'group', group, old)

        # Recalculating policies for USER
        for computer in computers:
            old = deepcopy(computer)
            del old["policies"][str(packages_policy['_id'])]
            object_changed(self.auth_user, 'computer', computer, old)

        # Recalculate policies for Chef nodes
        for node_id in ChefNode.list():
            node = ChefNode(node_id, self.api)
            logger.info('Checking node: %s'%(node_id))
            if ("gecos_ws_mgmt" in node.attributes) and ("software_mgmt" in node.attributes["gecos_ws_mgmt"]) and ("package_res" in node.attributes["gecos_ws_mgmt"]["software_mgmt"]):
                if "pkgs_to_remove" in node.attributes["gecos_ws_mgmt"]["software_mgmt"]["package_res"]:
                    logger.debug("Chef node %s contains a pkgs_to_remove value!"%(node_id))
                    # Remove pkgs_to_remove from mongodb node
                    logger.info("Remove 'pkgs_to_remove' attribute!")
                    try:
                        del node.attributes["gecos_ws_mgmt"]["software_mgmt"]["package_res"]["pkgs_to_remove"]
                        node.save()
                    except:
                        logger.warn("Problem deleting pkgs_to_remove value from node: %s"%(node_id))
                    
                if not "package_list" in node.attributes["gecos_ws_mgmt"]["software_mgmt"]["package_res"]:
                    logger.error("Chef node %s doesn\'t contains a package_list value!"%(node_id))
                    continue
                
                package_list = node.attributes["gecos_ws_mgmt"]["software_mgmt"]["package_res"]["package_list"]
                for element in package_list:
                    if not 'action' in element:
                        logger.debug('Chef node: %s doesn\'t have an action value in package_res! (package_list:%s)'%(node_id, str(package_list))) 
                        break

        # Final check
        bad_nodes = Search('node', "pkgs_to_remove:*", rows=1000, start=0, api=self.api)
        for node in bad_nodes:
            logger.warn('Detected bad node: %s'%(node.object.name))
            gecos_node = self.db.nodes.find_one({"node_chef_id": node.object.name})
            if gecos_node is None:
                logger.warn('Can\'t find node in MongoDB for: %s'%(node.object.name)) 
            else:
                logger.warn('For an unknown reason a computer called %s wasn\'t updated!'%(gecos_node['name'])) 
                
        logger.info('END ;)')
Example #34
0
    def command(self):
        api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, False,
                            self.settings.get('chef.version'))

        print '============ CHECKING ADMINISTRATOR USERS ============='
        # Check if all the GECOS CC administrators
        # are properly created in Chef 12
        admin_users = self.pyramid.userdb.list_users()
        for admin_user in admin_users:
            print 'Checking admin user: %s' % (admin_user['username'])

            # The email must be unique
            users_with_email = self.pyramid.userdb.list_users(
                {'email': admin_user['email']})
            if users_with_email.count() > 1:
                print "ERROR: more than one user with this email: %s" % (
                    admin_user['email'])

            # Get the Chef user
            chef_user = None
            try:
                chef_user = api['/users/%s' %
                                toChefUsername(admin_user['username'])]
            except ChefServerNotFoundError:
                pass

            if chef_user is None:
                # No chef user found
                print "WARNING: No Chef user found. We will try to create it!"

                chef_password = password_generator()
                try:
                    create_chef_admin_user(
                        api, self.settings,
                        toChefUsername(admin_user['username']), chef_password,
                        admin_user['email'])
                except ChefServerError, e:
                    print "ERROR: User not created in chef, error was: %s" % e
                    print "(Check /opt/opscode/embedded/service/opscode-erchef/log/requests.log* for more info)"
                    sys.exit(1)

                chef_user = api['/users/%s' %
                                toChefUsername(admin_user['username'])]

            # Check the email of the chef user
            if chef_user['email'] != admin_user['email']:
                print "WARNING: The chef user email and the GECOS CC user email doesn't match!"
                print "Try to change the chef user email!"
                chef_user['email'] = admin_user['email']
                api.api_request('PUT',
                                '/users/%s' %
                                (toChefUsername(admin_user['username'])),
                                data=chef_user)

            # Check if the administrator belongs to the "admins" group in the "default" organization
            admins_group = None
            try:
                admins_group = api['/organizations/default/groups/admins']
            except ChefServerNotFoundError:
                pass

            if not toChefUsername(
                    admin_user['username']) in admins_group['users']:
                print "WARNING: GECOS administrator is not a chef administrator for the default organization. We will try to change this!"

                # Check if exists an association request for this user
                assoc_requests = None
                try:
                    assoc_requests = api[
                        '/organizations/default/association_requests']
                except ChefServerNotFoundError:
                    pass

                association_id = None
                for req in assoc_requests:
                    if req["username"] == toChefUsername(
                            admin_user['username']):
                        association_id = req["id"]

                if association_id is None:
                    # Set an association request for the user in that organization
                    try:
                        data = {"user": toChefUsername(admin_user['username'])}
                        response = api.api_request(
                            'POST',
                            '/organizations/default/association_requests',
                            data=data)
                        association_id = response["uri"].split("/")[-1]
                    except ChefServerError:
                        # Association already exists?
                        pass

                if association_id is not None:
                    # Accept the association request
                    api.api_request(
                        'PUT',
                        '/users/%s/association_requests/%s' % (toChefUsername(
                            admin_user['username']), association_id),
                        data={"response": 'accept'})

                # Add the user to the group
                admins_group['users'].append(
                    toChefUsername(admin_user['username']))
                api.api_request('PUT',
                                '/organizations/default/groups/admins',
                                data={
                                    "groupname": admins_group["groupname"],
                                    "actors": {
                                        "users": admins_group['users'],
                                        "groups": admins_group["groups"]
                                    }
                                })
    def command(self):
        # Initialization
        self.api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, False, self.settings.get('chef.version'))

        self.db = self.pyramid.db
        self.referenced_data_type = {}
        self.referenced_data_type['storage_can_view'] = 'storage'
        self.referenced_data_type['repository_can_view'] = 'repository'
        self.referenced_data_type['printer_can_view'] = 'printer'
        
        
        # Get all the policies structures
        logger.info('Getting all the policies structures from database...')
        dbpolicies = self.db.policies.find()
        self.policiesdata = {}
        self.slug_check = {}
        for policy in dbpolicies:
            logger.debug('Addig to dictionary: %s => %s'%(policy['_id'], json.dumps(policy['schema'])))
            self.policiesdata[str(policy['_id'])] = policy
            
            # Check policy slug field (must be unique)
            if policy['slug'] in self.slug_check:
                logger.error("There are more than one policy with '%s' slug!"%(policy['slug']))
            else:
                self.slug_check[policy['slug']] = policy
                
            # Check policy serialization
            try:
                logger.debug('Serialized policy: %s'%(json.dumps(Policy().serialize(policy))))
            except Exception as err:
                logger.error('Policy %s with slug %s can\'t be serialized: %s'%(policy['_id'], policy['slug'], str(err)))
                
        
        logger.info('Checking tree...')
        # Look for the root of the nodes tree
        root_nodes = self.db.nodes.find({"path" : "root"})    
        for root in root_nodes:        
            self.check_node_and_subnodes(root)
        
        logger.info('Checking chef node references...')
        # Check the references to Chef nodes
        computers = self.db.nodes.find({"type" : "computer"})    
        for computer in computers:  
            if "node_chef_id" in computer:
                # Check Chef node
                computer_node = ChefNode(computer['node_chef_id'], self.api)
                logger.info("Computer: %s Chef ID: %s"%(computer['name'], computer['node_chef_id']))
                if not computer_node.exists:
                    logger.error("No Chef node with ID %s!"%(computer['node_chef_id']))
                
            else:
                logger.error("No Chef ID in '%s' computer!"%(computer['name']))

                
        logger.info('Checking MongoDB computer references...')
        # Check the references to computer nodes
        for node_id in ChefNode.list():
            found = False
            computers = self.db.nodes.find({"node_chef_id" : node_id})    
            for computer in computers:   
                found = True
                
            if not found:
                pclabel = "(No OHAI-GECOS data in the node)"
                computer_node = ChefNode(node_id, self.api)
                try:
                    pclabel = "(pclabel = %s)"%( computer_node.attributes.get_dotted('ohai_gecos.pclabel') )
                except KeyError:
                    pass
                        
                logger.error("No computer node for Chef ID: '%s' %s!"%(node_id, pclabel))
        
        
        logger.info('END ;)')