def get_services_by_name(servicename): """ GET /system/services/<servicename> :param request_inputs: :param servicename: :param hostid: :return: """ request_inputs = anchore_engine.apis.do_request_prep(request, default_params={}) user_auth = request_inputs['auth'] params = request_inputs['params'] return_object = [] httpcode = 500 try: client = CatalogClient(user=user_auth[0], password=user_auth[1]) service_records = client.get_service(servicename=servicename) for service_record in service_records: return_object.append( make_response_service(user_auth, service_record, params)) httpcode = 200 except Exception as err: return_object = anchore_engine.common.helpers.make_response_error( err, in_httpcode=httpcode) httpcode = return_object['httpcode'] return (return_object, httpcode)
def run_feeds_update(cls, json_obj=None, force_flush=False): """ Creates a task and runs it, optionally with a thread if locking is enabled. :return: """ error = None feeds = None with session_scope() as session: mgr = identities.manager_factory.for_session(session) system_user = mgr.get_system_credentials() catalog_client = CatalogClient(user=system_user[0], password=system_user[1]) try: feeds = get_selected_feeds_to_sync(localconfig.get_config()) if json_obj: task = cls.from_json(json_obj) if not task: return None task.feeds = feeds else: task = FeedsUpdateTask(feeds_to_sync=feeds, flush=force_flush) # Create feed task begin event try: catalog_client.add_event(FeedSyncStart(groups=feeds if feeds else 'all')) except: log.exception('Ignoring event generation error before feed sync') result = [] if cls.locking_enabled: # system_user = get_system_user_auth() run_target_with_lease(user_auth=system_user, lease_id='feed_sync', ttl=90, target=lambda: result.append(task.execute())) # A bit of work-around for the lambda def to get result from thread execution if result: result = result[0] else: result = task.execute() return result except LeaseAcquisitionFailedError as ex: error = ex log.exception('Could not acquire lock on feed sync, likely another sync already in progress') raise Exception('Cannot execute feed sync, lock is held by another feed sync in progress') except Exception as e: error = e log.exception('Error executing feeds update') raise e finally: # log feed sync event try: if error: catalog_client.add_event(FeedSyncFail(groups=feeds if feeds else 'all', error=error)) else: catalog_client.add_event(FeedSyncComplete(groups=feeds if feeds else 'all')) except: log.exception('Ignoring event generation error after feed sync')
def notify_event(event: EventBase, client: CatalogClient, operation_id=None): """ Send an event or just log it if client is None Always log the event to info level """ if client: try: client.add_event(event) except Exception as e: logger.warn("Error adding feed start event: {}".format(e)) try: logger.info("Event: {} (operation_id={})".format(event.to_json(), operation_id)) except: logger.exception("Error logging event")
def update_catalog_image_status( client: CatalogClient, image_digest: str, image_record: dict, new_analysis_status=None, new_image_status=None, ) -> dict: """ Update the analysis and/or image status for the record, one of new_analysis_status and new_image_status must be non-None :param client: :param image_digest: :param image_record: :param new_analysis_status: str new analysis_status value, options :param new_image_status: str new image status value, optional :return: """ if not (new_analysis_status or new_image_status): raise ValueError( "one of new_analysis_status or new_image_status must be non None") if new_analysis_status: image_record["analysis_status"] = new_analysis_status if new_image_status: image_record["image_status"] = new_image_status rc = client.update_image(image_digest, image_record) return image_record
def get_content( manifest: InternalImportManifest, client: CatalogClient, ) -> dict: content_map = {} for content_ref in manifest.contents: logger.info( "loading import content type %s from %s/%s", content_ref.content_type, content_ref.bucket, content_ref.key, ) raw = client.get_document(content_ref.bucket, content_ref.key) if content_ref.content_type in JSON_CONTENT_TYPES: content_map[content_ref.content_type] = json.loads(raw) else: content_map[content_ref.content_type] = raw return content_map
def imagepolicywebhook(bodycontent): # TODO - while the image policy webhook feature is in k8s beta, we've decided to make any errors that occur during check still respond with 'allowed: True'. This should be reverted to default to 'False' on any error, once the k8s feature is further along return_object = { "apiVersion": "imagepolicy.k8s.io/v1alpha1", "kind": "ImageReview", "status": { "allowed": True, "reason": "all images passed anchore policy evaluation" } } httpcode = 200 try: request_inputs = anchore_engine.apis.do_request_prep(connexion.request, default_params={}) user_auth = request_inputs['auth'] method = request_inputs['method'] params = request_inputs['params'] userId = request_inputs['userId'] try: final_allowed = True reason = "unset" try: try: #incoming = json.loads(bodycontent) incoming = bodycontent logger.debug("incoming post data: " + json.dumps(incoming, indent=4)) except Exception as err: raise Exception("could not load post data as json: " + str(err)) try: requestUserId = None requestPolicyId = None # see if the request from k8s contains an anchore policy and/or whitelist name if 'annotations' in incoming['spec']: logger.debug( "incoming request contains annotations: " + json.dumps(incoming['spec']['annotations'], indent=4)) requestUserId = incoming['spec']['annotations'].pop( "anchore.image-policy.k8s.io/userId", None) requestPolicyId = incoming['spec']['annotations'].pop( "anchore.image-policy.k8s.io/policyBundleId", None) except Exception as err: raise Exception("could not parse out annotations: " + str(err)) if not requestUserId: raise Exception( "need to specify an anchore.image-policy.k8s.io/userId annotation with a valid anchore service username as a value" ) # TODO - get anchore system uber cred to access # this data on behalf of user? tough...maybe see # if kuber can make request as anchore-system so # that we can switch roles? localconfig = anchore_engine.configuration.localconfig.get_config( ) system_user_auth = localconfig['system_user_auth'] # TODO: zhill This is bad, this is identity switching, need to resolve (this is not a change to previous behavior, but that behavior was bad) with session_scope() as dbsession: mgr = manager_factory.for_session(dbsession) request_user_auth = mgr.get_credentials_for_userid( requestUserId) catalog = CatalogClient( user=request_user_auth[0], password=request_user_auth[1], as_account=requestUserId if requestUserId else ApiRequestContextProxy.effective_account()) reason = "all images passed anchore policy checks" final_action = False for el in incoming['spec']['containers']: image = el['image'] logger.debug("found image in request: " + str(image)) image_records = catalog.get_image(tag=image) if not image_records: raise Exception("could not find requested image (" + str(image) + ") in anchore service DB") for image_record in image_records: imageDigest = image_record['imageDigest'] for image_detail in image_record['image_detail']: fulltag = image_detail[ 'registry'] + "/" + image_detail[ 'repo'] + ':' + image_detail['tag'] result = catalog.get_eval_latest( tag=fulltag, imageDigest=imageDigest, policyId=requestPolicyId) if result: httpcode = 200 if result['final_action'].upper() not in [ 'GO', 'WARN' ]: final_action = False raise Exception( "image failed anchore policy check: " + json.dumps(result, indent=4)) else: final_action = True else: httpcode = 404 final_action = False raise Exception( "no anchore evaluation available for image: " + str(image)) final_allowed = final_action except Exception as err: reason = str(err) final_allowed = False httpcode = 200 return_object['status']['allowed'] = final_allowed return_object['status']['reason'] = reason anchore_engine.subsys.metrics.counter_inc( "anchore_image_policy_webhooks_evaluation_total", allowed=final_allowed) #logger.debug("final return: " + json.dumps(return_object, indent=4)) httpcode = 200 except Exception as err: return_object['reason'] = str(err) httpcode = 500 except Exception as err: return_object['reason'] = str(err) httpcode = 500 return (return_object, httpcode)
def emit_events(client: CatalogClient, analysis_events: list): for event in analysis_events: try: client.add_event(event) except: logger.error("Ignoring error sending event")