import { RequestInfo, RequestInit, Response } from 'node-fetch'; import { IntegrationLogger } from '@jupiterone/integration-sdk-core'; import { CalculatedIntegrationConfig } from '../../types'; import { assets, ClientDelayedRequestEvent, ClientRequestEvent, ClientResponseEvent, csapi, PortalInfo, QWebHostId, RateLimitConfig, RateLimitState, ResourceIteratee, RetryConfig, SimpleReturn, vmpc, was } from './types'; export * from './types'; export declare const DEFAULT_RETRY_CONFIG: RetryConfig; /** * An initial rate limit state for a standard subscription level. * * @see https://www.qualys.com/docs/qualys-api-limits.pdf for details on * subscription level rate limits. */ export declare const STANDARD_RATE_LIMIT_STATE: RateLimitState; export declare const DEFAULT_RATE_LIMIT_CONFIG: RateLimitConfig; export type QualysAPIClientConfig = { config: CalculatedIntegrationConfig; /** * Initializes the API client with a `RateLimitConfig`. * * @see DEFAULT_RATE_LIMIT_CONFIG */ rateLimitConfig?: Partial; /** * Initializes the API client with a `RateLimitState`. When not provided, the * `STANDARD_RATE_LIMIT_STATE` is used to be conservative. The state will * update based on the responses so that a customer with a bigger subscription * will get their benefits. * * @see STANDARD_RATE_LIMIT_STATE */ rateLimitState?: RateLimitState; /** * Initializes the API client witha `RetryConfig`. * * @see DEFAULT_RETRY_CONFIG */ retryConfig?: Partial; }; export type IterateHostDetectionsOptions = { /** * Filters provided to the listHostDetections API. This reduces the amount of * data fetched from the Qualys API. */ filters?: vmpc.ListHostDetectionsFilters; pagination?: { limit: number; }; /** * Include detection results data when listing host detections. This is * expensive due to the increased number of bytes transferred and processed in * the XML payload. */ includeResults?: boolean; useIncludeOnlyTags?: boolean; onRequestError?: (pageIds: number[], err: Error) => void; }; /** * An extension of a Response to simplify access to the body of SIMPLE_RETURN * responses. */ export type QualysAPIResponse = Response & { /** * Consume the body and return a Promise that resolves SIMPLE_RETURN content. * The result is cached since the body is consumed, to allow multiple calls. * * @returns SimpleReturn or undefined when the body is unavailable or not XML */ simpleReturn: () => Promise; /** * Consume the body and return a Promise that resolves details of error * responses. The result is cached since the body is consumed, to allow * multiple calls. * * @returns QualysAPIErrorDetails or undefined when the response is not an * error or the body is unavailable or not XML */ errorDetails: () => Promise; }; type QualysAPIErrorDetails = { status: number; code: number; text: string; }; export declare class QualysAPIClient { private events; private config; private retryConfig; private rateLimitConfig; private rateLimitState; private token; constructor({ config, retryConfig, rateLimitConfig, rateLimitState, }: QualysAPIClientConfig); onRequest(eventHandler: (event: ClientRequestEvent) => void): void; onDelayedRequest(eventHandler: (event: ClientDelayedRequestEvent) => void): void; onResponse(eventHandler: (event: ClientResponseEvent) => void, options?: { path?: string; }): void; /** * Uses the Activity Log endpoint to fetch a single record for the username * provided to execute the integration to verify that authentication works. * * ```sh * curl -u "username:password" -k \ * -H "X-Requested-With:curl" \ * "https://qualysapi.qualys.com/api/2.0/fo/activity_log/?action=list&username=username&truncation_limit=1" * ``` * * The response body contains CSV on 200, XML on some other error responses. */ verifyAuthentication(): Promise; fetchPortalInfo(): Promise; getToken(): Promise; /** * Iterate web applications. Details are minimal, it is necessary to request * details in a separate call. * * @see fetchScannedWebAppIds to simply obtain the scanned web app ID values */ iterateWebApps(iteratee: ResourceIteratee, options?: { filters?: was.ListWebAppsFilters; pagination?: was.ListWebAppsPagination; }): Promise; fetchScannedWebAppIds(): Promise; /** * Iterate web application vulnerability findings. */ iterateWebAppFindings(webAppIds: number[], iteratee: ResourceIteratee, options: { filters?: was.ListWebAppFindingsFilters; pagination?: { limit: number; offset?: number; }; onRequestError: (pageIds: number[], err: Error) => void; }): Promise; /** * Answers the complete set of scanned `QWebHostId`s provided by the Qualys VMDR * module. This does not include hosts that have never been scanned. * * Fetches all IDs in a single request. This is documented by Qualys as a best * practice for an implementation that will parallelize ingestion of other * data for the hosts. * * @see * https://github.com/QualysAPI/Qualys-API-Doc-Center/blob/master/Host%20List%20Detection%20API%20samples/Multithreading/multi_thread_hd.py * for recommended approach to fetching set of hosts to process. */ fetchScannedHostIds(): Promise; /** * Answers the complete set of scanned host IDs provided by the Qualys VMDR * module. This does not include hosts that have never been scanned. * * @param iteratee receives each page of host ID values * @param options optional values for pagination */ iterateScannedHostIds(iteratee: ResourceIteratee, options?: { filters?: vmpc.ListScannedHostIdsFilters; pagination?: vmpc.ListScannedHostIdsPagination; }): Promise; /** * Iterate details of hosts known to the Asset Manager. * * * [API Documentation](https://www.qualys.com/docs/qualys-asset-management-tagging-api-v2-user-guide.pdf) * * There are currently no [rate * limits](https://www.qualys.com/docs/qualys-api-limits.pdf) on the Asset * Manager APIs. * * @param hostIds a set of identified QWEB host IDs */ iterateHostDetails(hostIds: QWebHostId[], iteratee: ResourceIteratee, options?: { pagination?: { limit: number; }; onRequestError?: (pageIds: number[], err: Error) => void; }): Promise; /** * Fetch host details from asset manager. * * @param hostId a QWEB host ID */ fetchHostDetails(hostId: QWebHostId): Promise; /** * Iterate detected host vulnerabilities. * * These are not the vulnerabilities themselves, which come from a * vulnerability database by QID, but the findings of vulnerabilities for a * host. * * > Maximum benefit has seen when the batch size is set evenly throughout the * > number of parallel threads used. For example, a host detection call * > resulting in a return of 100k assets, and using 10 threads in parallel, * > would benefit the most by using a batch size of (100,000 / 10) = 10,000. * > To reduce having one thread slow down the entire process by hitting a * > congested server, you can break this out further into batches of 5,000 * > hosts, resulting in 20 output files. * > - https://www.qualys.com/docs/qualys-api-vmpc-user-guide.pdf * * @param hostIds the set of QWEB host IDs to fetch detections * @param iteratee receives each host and its detections * @param options configure detection fetch parameters */ iterateHostDetections(hostIds: QWebHostId[], iteratee: ResourceIteratee<{ host: vmpc.DetectionHost; detections: vmpc.HostDetection[]; }>, options?: IterateHostDetectionsOptions, logger?: IntegrationLogger): Promise; /** * Iterate Qualys vulnerabilities. * * @param qids the set of Qualys QIDs to fetch vulnerabilities * @param iteratee receives each vulnerability */ iterateVulnerabilities(qids: number[], iteratee: ResourceIteratee, options: { pagination?: { limit: number; }; onRequestError: (pageIds: number[], err: Error) => void; }): Promise; /** * Iterate containers. */ iterateContainers(iteratee: ResourceIteratee, options: { pagination?: { limit: number; offset?: number; }; onRequestError: (pageIds: number[], err: Error) => void; }): Promise; /** * Get image details. */ getImageDetails(iteratee: ResourceIteratee, options: { pagination?: { limit: number; offset?: number; }; onRequestError: (pageIds: number[], err: Error) => void; }): Promise; /** * Get image vulnerabilities. */ iterateImageVulnerabilities(imageSha: string, iteratee: ResourceIteratee): Promise; /** * @throws IntegrationProviderAPIError */ executeAuthenticatedAPIRequest(info: RequestInfo, init: RequestInit): Promise; /** * @throws IntegrationProviderAPIError */ executeAuthenticatedCSAPIRequest(info: RequestInfo, init: RequestInit): Promise; /** * Executes an API request and processes the body, handling 200 responses with * embedded error codes. * * @param endpoint an API endpoint having a path matching * `/qps/rest/:version/*` * @param init RequestInit argument for fetch * * @throws `TypeError` when request endpoint does not look like a QPS REST * value * @throws `IntegrationError` for unexpected response content-type * @throws `IntegrationProviderAPIError` when responseCode in 200 response body indicates an error * @throws `IntegrationProviderAuthorizationError` when Qualys license has * expired, an error that should be reported to user, not operator */ private executeQpsRestAPIRequest; private hashAPIRequest; /** * Executes a request and returns a response. * * Builds an APIRequest to include details for retry and rate limit management * and delegates execution to the `executeAPIRequest` utility function, which * handles retrying based on response codes and rate limit headers. * * @throws `IntegrationProviderAPIError` when request cannot be completed within * this.retryConfig.maxAttempts * @throws `IntegrationProviderAPIError` when response status indicates a failure */ private executeAPIRequest; private qualysAuthorization; private qualysAuthorizationCSApi; private qualysUrl; private qualysUrlCSApi; } //# sourceMappingURL=index.d.ts.map