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)
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): 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)
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
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
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
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
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 ;)')
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)
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.')
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.')
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): 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.')
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)
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 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): 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 ;)')