Ejemplos de Amazon Inspector con el SDK para Java 2.x - AWS SDK for Java 2.x

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Ejemplos de Amazon Inspector con el SDK para Java 2.x

Los siguientes ejemplos de código muestran cómo realizar acciones e implementar situaciones comunes AWS SDK for Java 2.x con Amazon Inspector.

Los conceptos básicos son ejemplos de código que muestran cómo realizar las operaciones esenciales dentro de un servicio.

Las acciones son extractos de código de programas más grandes y deben ejecutarse en contexto. Mientras las acciones muestran cómo llamar a las distintas funciones de servicio, es posible ver las acciones en contexto en los escenarios relacionados.

En cada ejemplo se incluye un enlace al código de origen completo, con instrucciones de configuración y ejecución del código en el contexto.

Introducción

En el siguiente ejemplo de código se muestra cómo empezar a utilizar .

SDK para Java 2.x
nota

Hay más información al respecto GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/** * Before running this Java V2 code example, set up your development * environment, including your credentials. * * For more information, see the following documentation topic: * * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html */ public class HelloInspector { private static final Logger logger = LoggerFactory.getLogger(HelloInspector.class); public static void main(String[] args) { logger.info("Hello Amazon Inspector!"); try (Inspector2Client inspectorClient = Inspector2Client.builder().build()) { logger.info("Listing member accounts for this Inspector administrator account..."); listMembers(inspectorClient); logger.info("The Hello Inspector example completed successfully."); } catch (Inspector2Exception e) { logger.error("Error: {}", e.getMessage()); logger.info("Troubleshooting:"); logger.info("1. Verify AWS credentials are configured"); logger.info("2. Check IAM permissions for Inspector2"); logger.info("3. Ensure Inspector2 is enabled in your account"); logger.info("4. Verify you're using a supported region"); } } /** * Lists all member accounts associated with the current Inspector administrator account. * * @param inspectorClient The Inspector2Client used to interact with AWS Inspector. */ public static void listMembers(Inspector2Client inspectorClient) { try { ListMembersRequest request = ListMembersRequest.builder() .maxResults(50) // optional: limit results .build(); ListMembersResponse response = inspectorClient.listMembers(request); List<Member> members = response.members(); if (members == null || members.isEmpty()) { logger.info("No member accounts found for this Inspector administrator account."); return; } logger.info("Found {} member account(s):", members.size()); for (Member member : members) { logger.info(" - Account ID: {}, Status: {}", member.accountId(), member.relationshipStatusAsString()); } } catch (Inspector2Exception e) { logger.error("Failed to list members: {}", e.awsErrorDetails().errorMessage()); } } }
  • Para obtener más información sobre la API, consulta ListMembersla Referencia AWS SDK for Java 2.x de la API.

Conceptos básicos

En el siguiente ejemplo de código, se muestra cómo:

  • Compruebe el estado de la cuenta del Inspector.

  • Asegúrese de que el Inspector esté activado.

  • Analice los hallazgos de seguridad.

  • Compruebe la cobertura del escaneo.

  • Cree un filtro de hallazgos.

  • Enumere los filtros existentes.

  • Compruebe el uso y los costes.

  • Obtenga estadísticas de cobertura.

  • Eliminar un filtro.

SDK para Java 2.x
nota

Hay más en marcha GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

Ejecute un escenario interactivo en el que se demuestren las características de .

/** * Before running this Java V2 code example, set up your development * environment, including your credentials. * <p> * For more information, see the following documentation topic: * <p> * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html */ public class InspectorScenario { public static final String DASHES = new String(new char[80]).replace("\0", "-"); private static final Logger logger = LoggerFactory.getLogger(InspectorScenario.class); private static final Scanner scanner = new Scanner(System.in); public static void main(String[] args) { InspectorActions inspectorActions = new InspectorActions(); logger.info("Amazon Inspector Basics Scenario"); logger.info(""" Amazon Inspector is a security assessment service provided by Amazon Web Services (AWS) that helps improve the security and compliance of applications deployed on AWS. It automatically assesses applications for vulnerabilities or deviations from best practices. By leveraging Amazon Inspector, users can gain insights into the overall security state of their application and identify potential security risks. This service operates by conducting both network and host-based assessments, allowing it to detect a wide range of security issues, including those related to operating systems, network configurations, and application dependencies. """); waitForInputToContinue(); try { runScenario(inspectorActions); logger.info(""); logger.info("Scenario completed successfully!"); logger.info(""); logger.info("What you learned:"); logger.info(" - How to check Inspector account status"); logger.info(" - How to enable Inspector"); logger.info(" - How to list and analyze findings"); logger.info(" - How to check coverage information"); logger.info(" - How to create and manage filters"); logger.info(" - How to track usage and costs"); logger.info(" - How to clean up resources"); logger.info(""); } catch (Exception ex) { logger.error("Scenario failed due to unexpected error: {}", ex.getMessage(), ex); } finally { scanner.close(); logger.info("Exiting..."); } } /** * Runs the Inspector scenario in a step-by-step sequence. * * All InspectorActions methods are asynchronous and return CompletableFutures. * Each step ends with .join(). Any async exception thrown during .join() will bubble up * */ public static void runScenario(InspectorActions actions) { String filterArn = null; boolean inspectorEnabled = false; try { // Step 1 logger.info(DASHES); logger.info("Step 1: Checking Inspector account status..."); String status = actions.getAccountStatusAsync().join(); logger.info(status); waitForInputToContinue(); // Step 2 logger.info(DASHES); logger.info("Step 2: Enabling Inspector..."); String message = actions.enableInspectorAsync(null).join(); logger.info(message); inspectorEnabled = true; // track that Inspector was enabled waitForInputToContinue(); // Step 3 logger.info(DASHES); logger.info("Step 3: Listing LOW severity findings..."); // Call the service method List<String> allFindings = actions.listLowSeverityFindingsAsync().join(); if (!allFindings.isEmpty()) { // Only proceed if there are findings String lastArn = allFindings.get(allFindings.size() - 1); logger.info("Look up details on: {}", lastArn); waitForInputToContinue(); String details = actions.getFindingDetailsAsync(lastArn).join(); logger.info(details); } else { logger.info("No LOW severity findings found."); } waitForInputToContinue(); // Step 4 logger.info(DASHES); logger.info("Step 4: Listing coverage..."); String coverage = actions.listCoverageAsync(5).join(); logger.info(coverage); waitForInputToContinue(); // Step 5 logger.info(DASHES); logger.info("Step 5: Creating filter..."); String filterName = "suppress-low-" + System.currentTimeMillis(); filterArn = actions.createLowSeverityFilterAsync(filterName, "Suppress low severity findings").join(); logger.info("Created filter: {}", filterArn); waitForInputToContinue(); // Step 6 logger.info(DASHES); logger.info("Step 6: Listing filters..."); String filters = actions.listFiltersAsync(10).join(); logger.info(filters); waitForInputToContinue(); // Step 7 logger.info(DASHES); logger.info("Step 7: Usage totals..."); String usage = actions.listUsageTotalsAsync(null, 10).join(); logger.info(usage); waitForInputToContinue(); // Step 8 logger.info(DASHES); logger.info("Step 8: Coverage statistics..."); String stats = actions.listCoverageStatisticsAsync().join(); logger.info(stats); waitForInputToContinue(); // Step 9 logger.info(DASHES); logger.info("Step 9: Delete filter?"); logger.info("Filter ARN: {}", filterArn); logger.info("Delete the filter and disable Inspector? (y/n)"); if (scanner.nextLine().trim().equalsIgnoreCase("y")) { actions.deleteFilterAsync(filterArn).join(); logger.info("Filter deleted."); String disableMsg = actions.disableInspectorAsync(null).join(); logger.info(disableMsg); inspectorEnabled = false; // track that Inspector was disabled } waitForInputToContinue(); } catch (Exception ex) { logger.error("Scenario encountered an error: {}", ex.getMessage(), ex); // Rethrow the exception throw ex; } finally { // Cleanup in case of an exception if (filterArn != null) { try { actions.deleteFilterAsync(filterArn).join(); logger.info("Cleanup: Filter deleted."); } catch (Exception e) { logger.warn("Failed to delete filter during cleanup: {}", e.getMessage(), e); } } if (inspectorEnabled) { try { actions.disableInspectorAsync(null).join(); logger.info("Cleanup: Inspector disabled."); } catch (Exception e) { logger.warn("Failed to disable Inspector during cleanup: {}", e.getMessage(), e); } } } } // Utility Method private static void waitForInputToContinue() { while (true) { logger.info(""); logger.info("Enter 'c' to continue:"); String input = scanner.nextLine().trim(); if (input.equalsIgnoreCase("c")) break; logger.info("Invalid input, try again."); } } }

Una clase contenedora para métodos del SDK de .

public class InspectorActions { private static Inspector2AsyncClient inspectorAsyncClient; private static final Logger logger = LoggerFactory.getLogger(InspectorActions.class); private static Inspector2AsyncClient getAsyncClient() { if (inspectorAsyncClient == null) { SdkAsyncHttpClient httpClient = NettyNioAsyncHttpClient.builder() .maxConcurrency(100) .connectionTimeout(Duration.ofSeconds(60)) .readTimeout(Duration.ofSeconds(60)) .writeTimeout(Duration.ofSeconds(60)) .build(); ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration.builder() .apiCallTimeout(Duration.ofMinutes(2)) .apiCallAttemptTimeout(Duration.ofSeconds(90)) .retryStrategy(RetryMode.STANDARD) .build(); inspectorAsyncClient = Inspector2AsyncClient.builder() .httpClient(httpClient) .overrideConfiguration(overrideConfig) .build(); } return inspectorAsyncClient; } /** * Enables AWS Inspector for the provided account(s) and default resource types. * * @param accountIds Optional list of AWS account IDs. */ public CompletableFuture<String> enableInspectorAsync(List<String> accountIds) { // The resource types to enable. List<ResourceScanType> resourceTypes = List.of( ResourceScanType.EC2, ResourceScanType.ECR, ResourceScanType.LAMBDA, ResourceScanType.LAMBDA_CODE ); // Build the request. EnableRequest.Builder requestBuilder = EnableRequest.builder() .resourceTypes(resourceTypes); if (accountIds != null && !accountIds.isEmpty()) { requestBuilder.accountIds(accountIds); } EnableRequest request = requestBuilder.build(); return getAsyncClient().enable(request) .whenComplete((response, exception) -> { if (exception != null) { Throwable cause = exception.getCause(); if (cause instanceof ValidationException) { throw new CompletionException( "Inspector may already be enabled for this account: %s".formatted(cause.getMessage()), cause ); } if (cause instanceof Inspector2Exception) { Inspector2Exception e = (Inspector2Exception) cause; throw new CompletionException( "AWS Inspector2 service error: %s".formatted(e.awsErrorDetails().errorMessage()), cause ); } throw new CompletionException( "Failed to enable Inspector: %s".formatted(exception.getMessage()), exception ); } }) .thenApply(response -> { StringBuilder summary = new StringBuilder("Enable results:\n"); if (response.accounts() == null || response.accounts().isEmpty()) { summary.append("Inspector may already be enabled for all target accounts."); return summary.toString(); } for (Account account : response.accounts()) { String accountId = account.accountId() != null ? account.accountId() : "Unknown"; String status = account.status() != null ? account.statusAsString() : "Unknown"; summary.append(" • Account: ").append(accountId) .append(" → Status: ").append(status).append("\n"); } return summary.toString(); }); } /** * Retrieves and prints the coverage statistics using a paginator. */ public CompletableFuture<String> listCoverageStatisticsAsync() { ListCoverageStatisticsRequest request = ListCoverageStatisticsRequest.builder() .build(); return getAsyncClient().listCoverageStatistics(request) .whenComplete((response, exception) -> { if (exception != null) { Throwable cause = exception.getCause(); if (cause instanceof ValidationException) { throw new CompletionException( "Validation error listing coverage statistics: %s".formatted(cause.getMessage()), cause ); } if (cause instanceof Inspector2Exception) { Inspector2Exception e = (Inspector2Exception) cause; throw new CompletionException( "Inspector2 service error: %s".formatted(e.awsErrorDetails().errorMessage()), e ); } throw new CompletionException( "Unexpected error listing coverage statistics: %s".formatted(exception.getMessage()), exception ); } }) .thenApply(response -> { List<Counts> countsList = response.countsByGroup(); StringBuilder sb = new StringBuilder(); if (countsList == null || countsList.isEmpty()) { sb.append("No coverage statistics available.\n"); return sb.toString(); } sb.append("Coverage Statistics:\n"); for (Counts c : countsList) { sb.append(" Group: ").append(c.groupKey()).append("\n") .append(" Total Count: ").append(c.count()).append("\n\n"); } return sb.toString(); }); } /** * Asynchronously lists Inspector2 usage totals using a paginator. * * @param accountIds optional list of account IDs * @param maxResults maximum results per page * @return CompletableFuture completed with formatted summary text */ public CompletableFuture<String> listUsageTotalsAsync( List<String> accountIds, int maxResults) { logger.info("Starting usage totals paginator…"); ListUsageTotalsRequest.Builder builder = ListUsageTotalsRequest.builder() .maxResults(maxResults); if (accountIds != null && !accountIds.isEmpty()) { builder.accountIds(accountIds); } ListUsageTotalsRequest request = builder.build(); ListUsageTotalsPublisher paginator = getAsyncClient().listUsageTotalsPaginator(request); StringBuilder summaryBuilder = new StringBuilder(); return paginator.subscribe(response -> { if (response.totals() != null && !response.totals().isEmpty()) { response.totals().forEach(total -> { if (total.usage() != null) { total.usage().forEach(usage -> { logger.info("Usage: {} = {}", usage.typeAsString(), usage.total()); summaryBuilder.append(usage.typeAsString()) .append(": ") .append(usage.total()) .append("\n"); }); } }); } else { logger.info("Page contained no usage totals."); } }).thenRun(() -> logger.info("Successfully listed usage totals.")) .thenApply(v -> { String summary = summaryBuilder.toString(); return summary.isEmpty() ? "No usage totals found." : summary; }).exceptionally(ex -> { Throwable cause = ex.getCause() != null ? ex.getCause() : ex; if (cause instanceof ValidationException ve) { throw new CompletionException( "Validation error listing usage totals: %s".formatted(ve.getMessage()), ve ); } throw new CompletionException("Failed to list usage totals", cause); }); } /** * Retrieves the account status using the Inspector2Client. */ public CompletableFuture<String> getAccountStatusAsync() { BatchGetAccountStatusRequest request = BatchGetAccountStatusRequest.builder() .accountIds(Collections.emptyList()) .build(); return getAsyncClient().batchGetAccountStatus(request) .whenComplete((response, exception) -> { if (exception != null) { Throwable cause = exception.getCause(); if (cause instanceof AccessDeniedException) { throw new CompletionException( "You do not have sufficient access: %s".formatted(cause.getMessage()), cause ); } if (cause instanceof Inspector2Exception) { Inspector2Exception e = (Inspector2Exception) cause; throw new CompletionException( "Inspector2 service error: %s".formatted(e.awsErrorDetails().errorMessage()), e ); } throw new CompletionException( "Unexpected error getting account status: %s".formatted(exception.getMessage()), exception ); } }) .thenApply(response -> { StringBuilder sb = new StringBuilder(); List<AccountState> accounts = response.accounts(); if (accounts == null || accounts.isEmpty()) { sb.append("No account status returned.\n"); return sb.toString(); } sb.append("Inspector Account Status:\n"); for (AccountState account : accounts) { String accountId = account.accountId() != null ? account.accountId() : "Unknown"; sb.append(" Account ID: ").append(accountId).append("\n"); // Overall account state if (account.state() != null && account.state().status() != null) { sb.append(" Overall State: ") .append(account.state().status()) .append("\n"); } else { sb.append(" Overall State: Unknown\n"); } // Resource state (only status available) ResourceState resources = account.resourceState(); if (resources != null) { sb.append(" Resource Status: available\n"); } sb.append("\n"); } return sb.toString(); }); } /** * Asynchronously lists Inspector2 filters using a paginator. * * @param maxResults maximum filters per page (nullable) * @return CompletableFuture completed with summary text */ public CompletableFuture<String> listFiltersAsync(Integer maxResults) { logger.info("Starting async filters paginator…"); ListFiltersRequest.Builder builder = ListFiltersRequest.builder(); if (maxResults != null) { builder.maxResults(maxResults); } ListFiltersRequest request = builder.build(); // Paginator from SDK ListFiltersPublisher paginator = getAsyncClient().listFiltersPaginator(request); StringBuilder collectedFilterIds = new StringBuilder(); return paginator.subscribe(response -> { response.filters().forEach(filter -> { logger.info("Filter: " + filter.arn()); collectedFilterIds.append(filter.arn()).append("\n"); }); }).thenApply(v -> { String result = collectedFilterIds.toString(); logger.info("Successfully listed all filters."); return result.isEmpty() ? "No filters found." : result; }).exceptionally(ex -> { Throwable cause = ex.getCause() != null ? ex.getCause() : ex; if (cause instanceof ValidationException ve) { throw new CompletionException( "Validation error listing filters: %s".formatted(ve.getMessage()), ve ); } throw new RuntimeException("Failed to list filters", ex); }); } /** * Creates a new LOW severity filter in AWS Inspector2 to suppress findings. * * @param filterName the name of the filter to create * @param description a descriptive string explaining the purpose of the filter * @return a CompletableFuture that completes with the ARN of the created filter * @throws CompletionException wraps any validation, Inspector2 service, or unexpected errors */ public CompletableFuture<String> createLowSeverityFilterAsync( String filterName, String description) { // Define a filter to match LOW severity findings. StringFilter severityFilter = StringFilter.builder() .value(Severity.LOW.toString()) .comparison(StringComparison.EQUALS) .build(); // Create filter criteria. FilterCriteria filterCriteria = FilterCriteria.builder() .severity(Collections.singletonList(severityFilter)) .build(); // Build the filter creation request. CreateFilterRequest request = CreateFilterRequest.builder() .name(filterName) .filterCriteria(filterCriteria) .action(FilterAction.SUPPRESS) .description(description) .build(); return getAsyncClient().createFilter(request) .whenComplete((response, exception) -> { if (exception != null) { Throwable cause = exception.getCause() != null ? exception.getCause() : exception; if (cause instanceof ValidationException ve) { throw new CompletionException( "Validation error creating filter: %s".formatted(ve.getMessage()), ve ); } if (cause instanceof Inspector2Exception e) { throw new CompletionException( "Inspector2 service error: %s".formatted(e.awsErrorDetails().errorMessage()), e ); } // Unexpected async error throw new CompletionException( "Unexpected error creating filter: %s".formatted(exception.getMessage()), exception ); } }) // Extract and return the ARN of the created filter. .thenApply(CreateFilterResponse::arn); } /** * Lists all AWS Inspector findings of LOW severity asynchronously. * * @return CompletableFuture containing a List of finding ARNs. * Returns an empty list if no LOW severity findings are found. */ public CompletableFuture<ArrayList<String>> listLowSeverityFindingsAsync() { logger.info("Starting async LOW severity findings paginator…"); // Build a filter criteria for LOW severity. StringFilter severityFilter = StringFilter.builder() .value(Severity.LOW.toString()) .comparison(StringComparison.EQUALS) .build(); FilterCriteria filterCriteria = FilterCriteria.builder() .severity(Collections.singletonList(severityFilter)) .build(); // Build the request. ListFindingsRequest request = ListFindingsRequest.builder() .filterCriteria(filterCriteria) .build(); ListFindingsPublisher paginator = getAsyncClient().listFindingsPaginator(request); List<String> allArns = Collections.synchronizedList(new ArrayList<>()); return paginator.subscribe(response -> { if (response.findings() != null && !response.findings().isEmpty()) { response.findings().forEach(finding -> { logger.info("Finding ARN: {}", finding.findingArn()); allArns.add(finding.findingArn()); }); } else { logger.info("Page contained no findings."); } }) .thenRun(() -> logger.info("Successfully listed all LOW severity findings.")) .thenApply(v -> new ArrayList<>(allArns)) // Return list instead of a formatted string .exceptionally(ex -> { Throwable cause = ex.getCause() != null ? ex.getCause() : ex; if (cause instanceof ValidationException ve) { throw new CompletionException( "Validation error listing LOW severity findings: %s".formatted(ve.getMessage()), ve ); } throw new RuntimeException("Failed to list LOW severity findings", ex); }); } /** * Lists AWS Inspector2 coverage details for scanned resources using a paginator. * * @param maxResults Maximum number of resources to return. */ public CompletableFuture<String> listCoverageAsync(int maxResults) { ListCoverageRequest initialRequest = ListCoverageRequest.builder() .maxResults(maxResults) .build(); ListCoveragePublisher paginator = getAsyncClient().listCoveragePaginator(initialRequest); StringBuilder summary = new StringBuilder(); return paginator.subscribe(response -> { List<CoveredResource> coveredResources = response.coveredResources(); if (coveredResources == null || coveredResources.isEmpty()) { summary.append("No coverage information available for this page.\n"); return; } Map<String, List<CoveredResource>> byType = coveredResources.stream() .collect(Collectors.groupingBy(CoveredResource::resourceTypeAsString)); byType.forEach((type, list) -> summary.append(" ").append(type) .append(": ").append(list.size()) .append(" resource(s)\n") ); // Include up to 3 sample resources per page for (int i = 0; i < Math.min(coveredResources.size(), 3); i++) { CoveredResource r = coveredResources.get(i); summary.append(" - ").append(r.resourceTypeAsString()) .append(": ").append(r.resourceId()).append("\n"); summary.append(" Scan Type: ").append(r.scanTypeAsString()).append("\n"); if (r.scanStatus() != null) { summary.append(" Status: ").append(r.scanStatus().statusCodeAsString()).append("\n"); } if (r.accountId() != null) { summary.append(" Account ID: ").append(r.accountId()).append("\n"); } summary.append("\n"); } }).thenApply(v -> { if (summary.length() == 0) { return "No coverage information found across all pages."; } else { return "Coverage Information:\n" + summary.toString(); } }).exceptionally(ex -> { Throwable cause = ex.getCause(); if (cause instanceof ValidationException) { throw new CompletionException( "Validation error listing coverage: " + cause.getMessage(), cause); } else if (cause instanceof Inspector2Exception e) { throw new CompletionException( "Inspector2 service error: " + e.awsErrorDetails().errorMessage(), e); } throw new CompletionException("Unexpected error listing coverage: " + ex.getMessage(), ex); }); } /** * Deletes an AWS Inspector2 filter. * * @param filterARN The ARN of the filter to delete. */ public CompletableFuture<Void> deleteFilterAsync(String filterARN) { return getAsyncClient().deleteFilter( DeleteFilterRequest.builder() .arn(filterARN) .build() ) .handle((response, exception) -> { if (exception != null) { Throwable cause = exception.getCause() != null ? exception.getCause() : exception; if (cause instanceof ResourceNotFoundException rnfe) { String msg = "Filter not found for ARN: %s".formatted(filterARN); logger.warn(msg, rnfe); throw new CompletionException(msg, rnfe); } throw new RuntimeException("Failed to delete the filter: " + cause, cause); } return null; }); } /** * Retrieves detailed information about a specific AWS Inspector2 finding asynchronously. * * @param findingArn The ARN of the finding to look up. * @return A {@link CompletableFuture} that, when completed, provides a formatted string * containing all available details for the finding. * @throws RuntimeException if the async call to Inspector2 fails. */ public CompletableFuture<String> getFindingDetailsAsync(String findingArn) { BatchGetFindingDetailsRequest request = BatchGetFindingDetailsRequest.builder() .findingArns(findingArn) .build(); return getAsyncClient().batchGetFindingDetails(request) .thenApply(response -> { if (response.findingDetails() == null || response.findingDetails().isEmpty()) { return String.format("No details found for ARN: ", findingArn); } StringBuilder sb = new StringBuilder(); response.findingDetails().forEach(detail -> { sb.append("Finding ARN: ").append(detail.findingArn()).append("\n") .append("Risk Score: ").append(detail.riskScore()).append("\n"); // ExploitObserved timings if (detail.exploitObserved() != null) { sb.append("Exploit First Seen: ").append(detail.exploitObserved().firstSeen()).append("\n") .append("Exploit Last Seen: ").append(detail.exploitObserved().lastSeen()).append("\n"); } // Reference URLs if (detail.hasReferenceUrls()) { sb.append("Reference URLs:\n"); detail.referenceUrls().forEach(url -> sb.append(" • ").append(url).append("\n")); } // Tools if (detail.hasTools()) { sb.append("Tools:\n"); detail.tools().forEach(tool -> sb.append(" • ").append(tool).append("\n")); } // TTPs if (detail.hasTtps()) { sb.append("TTPs:\n"); detail.ttps().forEach(ttp -> sb.append(" • ").append(ttp).append("\n")); } // CWEs if (detail.hasCwes()) { sb.append("CWEs:\n"); detail.cwes().forEach(cwe -> sb.append(" • ").append(cwe).append("\n")); } // Evidence if (detail.hasEvidences()) { sb.append("Evidence:\n"); detail.evidences().forEach(ev -> { sb.append(" - Severity: ").append(ev.severity()).append("\n"); }); } sb.append("\n"); }); return sb.toString(); }) .exceptionally(ex -> { Throwable cause = ex.getCause() != null ? ex.getCause() : ex; if (cause instanceof ResourceNotFoundException rnfe) { return "Finding not found: %s".formatted(findingArn); } // Fallback for other exceptions throw new RuntimeException("Failed to get finding details for ARN: " + findingArn, cause); }); } /** * Asynchronously disables AWS Inspector for the specified accounts and resource types. * * @param accountIds a {@link List} of AWS account IDs for which to disable Inspector; * may be {@code null} or empty to target the current account * @return a {@link CompletableFuture} that, when completed, returns a {@link String} * summarizing the disable results for each account * @throws CompletionException if the disable operation fails due to validation errors, * service errors, or other exceptions * @see <a href="https://docs.aws.amazon.com/inspector/latest/APIReference/API_Disable.html"> * AWS Inspector2 Disable API</a> */ public CompletableFuture<String> disableInspectorAsync(List<String> accountIds) { // The resource types to disable. List<ResourceScanType> resourceTypes = List.of( ResourceScanType.EC2, ResourceScanType.ECR, ResourceScanType.LAMBDA, ResourceScanType.LAMBDA_CODE ); // Build the request. DisableRequest.Builder requestBuilder = DisableRequest.builder() .resourceTypes(resourceTypes); if (accountIds != null && !accountIds.isEmpty()) { requestBuilder.accountIds(accountIds); } DisableRequest request = requestBuilder.build(); return getAsyncClient().disable(request) .whenComplete((response, exception) -> { if (exception != null) { Throwable cause = exception.getCause(); if (cause instanceof ValidationException) { throw new CompletionException( "Inspector may already be disabled for this account: %s".formatted(cause.getMessage()), cause ); } if (cause instanceof Inspector2Exception) { Inspector2Exception e = (Inspector2Exception) cause; throw new CompletionException( "AWS Inspector2 service error: %s".formatted(e.awsErrorDetails().errorMessage()), cause ); } throw new CompletionException( "Failed to disable Inspector: %s".formatted(exception.getMessage()), exception ); } }) .thenApply(response -> { StringBuilder summary = new StringBuilder("Disable results:\n"); if (response.accounts() == null || response.accounts().isEmpty()) { summary.append("Inspector may already be disabled for all target accounts."); return summary.toString(); } for (Account account : response.accounts()) { String accountId = account.accountId() != null ? account.accountId() : "Unknown"; String status = account.status() != null ? account.statusAsString() : "Unknown"; summary.append(" • Account: ").append(accountId) .append(" → Status: ").append(status).append("\n"); } return summary.toString(); }); } }

Acciones

En el siguiente ejemplo de código, se muestra cómo utilizar BatchGetAccountStatus.

SDK para Java 2.x
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/** * Retrieves the account status using the Inspector2Client. */ public CompletableFuture<String> getAccountStatusAsync() { BatchGetAccountStatusRequest request = BatchGetAccountStatusRequest.builder() .accountIds(Collections.emptyList()) .build(); return getAsyncClient().batchGetAccountStatus(request) .whenComplete((response, exception) -> { if (exception != null) { Throwable cause = exception.getCause(); if (cause instanceof AccessDeniedException) { throw new CompletionException( "You do not have sufficient access: %s".formatted(cause.getMessage()), cause ); } if (cause instanceof Inspector2Exception) { Inspector2Exception e = (Inspector2Exception) cause; throw new CompletionException( "Inspector2 service error: %s".formatted(e.awsErrorDetails().errorMessage()), e ); } throw new CompletionException( "Unexpected error getting account status: %s".formatted(exception.getMessage()), exception ); } }) .thenApply(response -> { StringBuilder sb = new StringBuilder(); List<AccountState> accounts = response.accounts(); if (accounts == null || accounts.isEmpty()) { sb.append("No account status returned.\n"); return sb.toString(); } sb.append("Inspector Account Status:\n"); for (AccountState account : accounts) { String accountId = account.accountId() != null ? account.accountId() : "Unknown"; sb.append(" Account ID: ").append(accountId).append("\n"); // Overall account state if (account.state() != null && account.state().status() != null) { sb.append(" Overall State: ") .append(account.state().status()) .append("\n"); } else { sb.append(" Overall State: Unknown\n"); } // Resource state (only status available) ResourceState resources = account.resourceState(); if (resources != null) { sb.append(" Resource Status: available\n"); } sb.append("\n"); } return sb.toString(); }); }
  • Para obtener más información sobre la API, consulta BatchGetAccountStatusla Referencia AWS SDK for Java 2.x de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar BatchGetFindingDetails.

SDK para Java 2.x
nota

Hay más información al respecto GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/** * Retrieves detailed information about a specific AWS Inspector2 finding asynchronously. * * @param findingArn The ARN of the finding to look up. * @return A {@link CompletableFuture} that, when completed, provides a formatted string * containing all available details for the finding. * @throws RuntimeException if the async call to Inspector2 fails. */ public CompletableFuture<String> getFindingDetailsAsync(String findingArn) { BatchGetFindingDetailsRequest request = BatchGetFindingDetailsRequest.builder() .findingArns(findingArn) .build(); return getAsyncClient().batchGetFindingDetails(request) .thenApply(response -> { if (response.findingDetails() == null || response.findingDetails().isEmpty()) { return String.format("No details found for ARN: ", findingArn); } StringBuilder sb = new StringBuilder(); response.findingDetails().forEach(detail -> { sb.append("Finding ARN: ").append(detail.findingArn()).append("\n") .append("Risk Score: ").append(detail.riskScore()).append("\n"); // ExploitObserved timings if (detail.exploitObserved() != null) { sb.append("Exploit First Seen: ").append(detail.exploitObserved().firstSeen()).append("\n") .append("Exploit Last Seen: ").append(detail.exploitObserved().lastSeen()).append("\n"); } // Reference URLs if (detail.hasReferenceUrls()) { sb.append("Reference URLs:\n"); detail.referenceUrls().forEach(url -> sb.append(" • ").append(url).append("\n")); } // Tools if (detail.hasTools()) { sb.append("Tools:\n"); detail.tools().forEach(tool -> sb.append(" • ").append(tool).append("\n")); } // TTPs if (detail.hasTtps()) { sb.append("TTPs:\n"); detail.ttps().forEach(ttp -> sb.append(" • ").append(ttp).append("\n")); } // CWEs if (detail.hasCwes()) { sb.append("CWEs:\n"); detail.cwes().forEach(cwe -> sb.append(" • ").append(cwe).append("\n")); } // Evidence if (detail.hasEvidences()) { sb.append("Evidence:\n"); detail.evidences().forEach(ev -> { sb.append(" - Severity: ").append(ev.severity()).append("\n"); }); } sb.append("\n"); }); return sb.toString(); }) .exceptionally(ex -> { Throwable cause = ex.getCause() != null ? ex.getCause() : ex; if (cause instanceof ResourceNotFoundException rnfe) { return "Finding not found: %s".formatted(findingArn); } // Fallback for other exceptions throw new RuntimeException("Failed to get finding details for ARN: " + findingArn, cause); }); }
  • Para obtener más información sobre la API, consulta BatchGetFindingDetailsla Referencia AWS SDK for Java 2.x de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar CreateFilter.

SDK para Java 2.x
nota

Hay más información al respecto GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/** * Creates a new LOW severity filter in AWS Inspector2 to suppress findings. * * @param filterName the name of the filter to create * @param description a descriptive string explaining the purpose of the filter * @return a CompletableFuture that completes with the ARN of the created filter * @throws CompletionException wraps any validation, Inspector2 service, or unexpected errors */ public CompletableFuture<String> createLowSeverityFilterAsync( String filterName, String description) { // Define a filter to match LOW severity findings. StringFilter severityFilter = StringFilter.builder() .value(Severity.LOW.toString()) .comparison(StringComparison.EQUALS) .build(); // Create filter criteria. FilterCriteria filterCriteria = FilterCriteria.builder() .severity(Collections.singletonList(severityFilter)) .build(); // Build the filter creation request. CreateFilterRequest request = CreateFilterRequest.builder() .name(filterName) .filterCriteria(filterCriteria) .action(FilterAction.SUPPRESS) .description(description) .build(); return getAsyncClient().createFilter(request) .whenComplete((response, exception) -> { if (exception != null) { Throwable cause = exception.getCause() != null ? exception.getCause() : exception; if (cause instanceof ValidationException ve) { throw new CompletionException( "Validation error creating filter: %s".formatted(ve.getMessage()), ve ); } if (cause instanceof Inspector2Exception e) { throw new CompletionException( "Inspector2 service error: %s".formatted(e.awsErrorDetails().errorMessage()), e ); } // Unexpected async error throw new CompletionException( "Unexpected error creating filter: %s".formatted(exception.getMessage()), exception ); } }) // Extract and return the ARN of the created filter. .thenApply(CreateFilterResponse::arn); }
  • Para obtener más información sobre la API, consulta CreateFilterla Referencia AWS SDK for Java 2.x de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar DeleteFilter.

SDK para Java 2.x
nota

Hay más información al respecto GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/** * Deletes an AWS Inspector2 filter. * * @param filterARN The ARN of the filter to delete. */ public CompletableFuture<Void> deleteFilterAsync(String filterARN) { return getAsyncClient().deleteFilter( DeleteFilterRequest.builder() .arn(filterARN) .build() ) .handle((response, exception) -> { if (exception != null) { Throwable cause = exception.getCause() != null ? exception.getCause() : exception; if (cause instanceof ResourceNotFoundException rnfe) { String msg = "Filter not found for ARN: %s".formatted(filterARN); logger.warn(msg, rnfe); throw new CompletionException(msg, rnfe); } throw new RuntimeException("Failed to delete the filter: " + cause, cause); } return null; }); }
  • Para obtener más información sobre la API, consulta DeleteFilterla Referencia AWS SDK for Java 2.x de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar Disable.

SDK para Java 2.x
nota

Hay más información al respecto GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/** * Asynchronously disables AWS Inspector for the specified accounts and resource types. * * @param accountIds a {@link List} of AWS account IDs for which to disable Inspector; * may be {@code null} or empty to target the current account * @return a {@link CompletableFuture} that, when completed, returns a {@link String} * summarizing the disable results for each account * @throws CompletionException if the disable operation fails due to validation errors, * service errors, or other exceptions * @see <a href="https://docs.aws.amazon.com/inspector/latest/APIReference/API_Disable.html"> * AWS Inspector2 Disable API</a> */ public CompletableFuture<String> disableInspectorAsync(List<String> accountIds) { // The resource types to disable. List<ResourceScanType> resourceTypes = List.of( ResourceScanType.EC2, ResourceScanType.ECR, ResourceScanType.LAMBDA, ResourceScanType.LAMBDA_CODE ); // Build the request. DisableRequest.Builder requestBuilder = DisableRequest.builder() .resourceTypes(resourceTypes); if (accountIds != null && !accountIds.isEmpty()) { requestBuilder.accountIds(accountIds); } DisableRequest request = requestBuilder.build(); return getAsyncClient().disable(request) .whenComplete((response, exception) -> { if (exception != null) { Throwable cause = exception.getCause(); if (cause instanceof ValidationException) { throw new CompletionException( "Inspector may already be disabled for this account: %s".formatted(cause.getMessage()), cause ); } if (cause instanceof Inspector2Exception) { Inspector2Exception e = (Inspector2Exception) cause; throw new CompletionException( "AWS Inspector2 service error: %s".formatted(e.awsErrorDetails().errorMessage()), cause ); } throw new CompletionException( "Failed to disable Inspector: %s".formatted(exception.getMessage()), exception ); } }) .thenApply(response -> { StringBuilder summary = new StringBuilder("Disable results:\n"); if (response.accounts() == null || response.accounts().isEmpty()) { summary.append("Inspector may already be disabled for all target accounts."); return summary.toString(); } for (Account account : response.accounts()) { String accountId = account.accountId() != null ? account.accountId() : "Unknown"; String status = account.status() != null ? account.statusAsString() : "Unknown"; summary.append(" • Account: ").append(accountId) .append(" → Status: ").append(status).append("\n"); } return summary.toString(); }); }
  • Para obtener más información sobre la API, consulta la sección Inhabilitar en la referencia de la AWS SDK for Java 2.x API.

En el siguiente ejemplo de código, se muestra cómo utilizar Enable.

SDK para Java 2.x
nota

Hay más información al respecto GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/** * Enables AWS Inspector for the provided account(s) and default resource types. * * @param accountIds Optional list of AWS account IDs. */ public CompletableFuture<String> enableInspectorAsync(List<String> accountIds) { // The resource types to enable. List<ResourceScanType> resourceTypes = List.of( ResourceScanType.EC2, ResourceScanType.ECR, ResourceScanType.LAMBDA, ResourceScanType.LAMBDA_CODE ); // Build the request. EnableRequest.Builder requestBuilder = EnableRequest.builder() .resourceTypes(resourceTypes); if (accountIds != null && !accountIds.isEmpty()) { requestBuilder.accountIds(accountIds); } EnableRequest request = requestBuilder.build(); return getAsyncClient().enable(request) .whenComplete((response, exception) -> { if (exception != null) { Throwable cause = exception.getCause(); if (cause instanceof ValidationException) { throw new CompletionException( "Inspector may already be enabled for this account: %s".formatted(cause.getMessage()), cause ); } if (cause instanceof Inspector2Exception) { Inspector2Exception e = (Inspector2Exception) cause; throw new CompletionException( "AWS Inspector2 service error: %s".formatted(e.awsErrorDetails().errorMessage()), cause ); } throw new CompletionException( "Failed to enable Inspector: %s".formatted(exception.getMessage()), exception ); } }) .thenApply(response -> { StringBuilder summary = new StringBuilder("Enable results:\n"); if (response.accounts() == null || response.accounts().isEmpty()) { summary.append("Inspector may already be enabled for all target accounts."); return summary.toString(); } for (Account account : response.accounts()) { String accountId = account.accountId() != null ? account.accountId() : "Unknown"; String status = account.status() != null ? account.statusAsString() : "Unknown"; summary.append(" • Account: ").append(accountId) .append(" → Status: ").append(status).append("\n"); } return summary.toString(); }); }
  • Para obtener más información sobre la API, consulta la sección Habilitar en la referencia de la AWS SDK for Java 2.x API.

En el siguiente ejemplo de código, se muestra cómo utilizar ListCoverage.

SDK para Java 2.x
nota

Hay más información al respecto GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/** * Lists AWS Inspector2 coverage details for scanned resources using a paginator. * * @param maxResults Maximum number of resources to return. */ public CompletableFuture<String> listCoverageAsync(int maxResults) { ListCoverageRequest initialRequest = ListCoverageRequest.builder() .maxResults(maxResults) .build(); ListCoveragePublisher paginator = getAsyncClient().listCoveragePaginator(initialRequest); StringBuilder summary = new StringBuilder(); return paginator.subscribe(response -> { List<CoveredResource> coveredResources = response.coveredResources(); if (coveredResources == null || coveredResources.isEmpty()) { summary.append("No coverage information available for this page.\n"); return; } Map<String, List<CoveredResource>> byType = coveredResources.stream() .collect(Collectors.groupingBy(CoveredResource::resourceTypeAsString)); byType.forEach((type, list) -> summary.append(" ").append(type) .append(": ").append(list.size()) .append(" resource(s)\n") ); // Include up to 3 sample resources per page for (int i = 0; i < Math.min(coveredResources.size(), 3); i++) { CoveredResource r = coveredResources.get(i); summary.append(" - ").append(r.resourceTypeAsString()) .append(": ").append(r.resourceId()).append("\n"); summary.append(" Scan Type: ").append(r.scanTypeAsString()).append("\n"); if (r.scanStatus() != null) { summary.append(" Status: ").append(r.scanStatus().statusCodeAsString()).append("\n"); } if (r.accountId() != null) { summary.append(" Account ID: ").append(r.accountId()).append("\n"); } summary.append("\n"); } }).thenApply(v -> { if (summary.length() == 0) { return "No coverage information found across all pages."; } else { return "Coverage Information:\n" + summary.toString(); } }).exceptionally(ex -> { Throwable cause = ex.getCause(); if (cause instanceof ValidationException) { throw new CompletionException( "Validation error listing coverage: " + cause.getMessage(), cause); } else if (cause instanceof Inspector2Exception e) { throw new CompletionException( "Inspector2 service error: " + e.awsErrorDetails().errorMessage(), e); } throw new CompletionException("Unexpected error listing coverage: " + ex.getMessage(), ex); }); }
  • Para obtener más información sobre la API, consulta ListCoveragela Referencia AWS SDK for Java 2.x de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar ListCoverageStatistics.

SDK para Java 2.x
nota

Hay más información al respecto GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/** * Retrieves and prints the coverage statistics using a paginator. */ public CompletableFuture<String> listCoverageStatisticsAsync() { ListCoverageStatisticsRequest request = ListCoverageStatisticsRequest.builder() .build(); return getAsyncClient().listCoverageStatistics(request) .whenComplete((response, exception) -> { if (exception != null) { Throwable cause = exception.getCause(); if (cause instanceof ValidationException) { throw new CompletionException( "Validation error listing coverage statistics: %s".formatted(cause.getMessage()), cause ); } if (cause instanceof Inspector2Exception) { Inspector2Exception e = (Inspector2Exception) cause; throw new CompletionException( "Inspector2 service error: %s".formatted(e.awsErrorDetails().errorMessage()), e ); } throw new CompletionException( "Unexpected error listing coverage statistics: %s".formatted(exception.getMessage()), exception ); } }) .thenApply(response -> { List<Counts> countsList = response.countsByGroup(); StringBuilder sb = new StringBuilder(); if (countsList == null || countsList.isEmpty()) { sb.append("No coverage statistics available.\n"); return sb.toString(); } sb.append("Coverage Statistics:\n"); for (Counts c : countsList) { sb.append(" Group: ").append(c.groupKey()).append("\n") .append(" Total Count: ").append(c.count()).append("\n\n"); } return sb.toString(); }); }
  • Para obtener más información sobre la API, consulta ListCoverageStatisticsla Referencia AWS SDK for Java 2.x de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar ListFilters.

SDK para Java 2.x
nota

Hay más información al respecto GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/** * Asynchronously lists Inspector2 filters using a paginator. * * @param maxResults maximum filters per page (nullable) * @return CompletableFuture completed with summary text */ public CompletableFuture<String> listFiltersAsync(Integer maxResults) { logger.info("Starting async filters paginator…"); ListFiltersRequest.Builder builder = ListFiltersRequest.builder(); if (maxResults != null) { builder.maxResults(maxResults); } ListFiltersRequest request = builder.build(); // Paginator from SDK ListFiltersPublisher paginator = getAsyncClient().listFiltersPaginator(request); StringBuilder collectedFilterIds = new StringBuilder(); return paginator.subscribe(response -> { response.filters().forEach(filter -> { logger.info("Filter: " + filter.arn()); collectedFilterIds.append(filter.arn()).append("\n"); }); }).thenApply(v -> { String result = collectedFilterIds.toString(); logger.info("Successfully listed all filters."); return result.isEmpty() ? "No filters found." : result; }).exceptionally(ex -> { Throwable cause = ex.getCause() != null ? ex.getCause() : ex; if (cause instanceof ValidationException ve) { throw new CompletionException( "Validation error listing filters: %s".formatted(ve.getMessage()), ve ); } throw new RuntimeException("Failed to list filters", ex); }); }
  • Para obtener más información sobre la API, consulta ListFiltersla Referencia AWS SDK for Java 2.x de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar ListFindings.

SDK para Java 2.x
nota

Hay más información al respecto GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/** * Lists all AWS Inspector findings of LOW severity asynchronously. * * @return CompletableFuture containing a List of finding ARNs. * Returns an empty list if no LOW severity findings are found. */ public CompletableFuture<ArrayList<String>> listLowSeverityFindingsAsync() { logger.info("Starting async LOW severity findings paginator…"); // Build a filter criteria for LOW severity. StringFilter severityFilter = StringFilter.builder() .value(Severity.LOW.toString()) .comparison(StringComparison.EQUALS) .build(); FilterCriteria filterCriteria = FilterCriteria.builder() .severity(Collections.singletonList(severityFilter)) .build(); // Build the request. ListFindingsRequest request = ListFindingsRequest.builder() .filterCriteria(filterCriteria) .build(); ListFindingsPublisher paginator = getAsyncClient().listFindingsPaginator(request); List<String> allArns = Collections.synchronizedList(new ArrayList<>()); return paginator.subscribe(response -> { if (response.findings() != null && !response.findings().isEmpty()) { response.findings().forEach(finding -> { logger.info("Finding ARN: {}", finding.findingArn()); allArns.add(finding.findingArn()); }); } else { logger.info("Page contained no findings."); } }) .thenRun(() -> logger.info("Successfully listed all LOW severity findings.")) .thenApply(v -> new ArrayList<>(allArns)) // Return list instead of a formatted string .exceptionally(ex -> { Throwable cause = ex.getCause() != null ? ex.getCause() : ex; if (cause instanceof ValidationException ve) { throw new CompletionException( "Validation error listing LOW severity findings: %s".formatted(ve.getMessage()), ve ); } throw new RuntimeException("Failed to list LOW severity findings", ex); }); }
  • Para obtener más información sobre la API, consulta ListFindingsla Referencia AWS SDK for Java 2.x de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar ListUsageTotals.

SDK para Java 2.x
nota

Hay más información al respecto GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/** * Asynchronously lists Inspector2 usage totals using a paginator. * * @param accountIds optional list of account IDs * @param maxResults maximum results per page * @return CompletableFuture completed with formatted summary text */ public CompletableFuture<String> listUsageTotalsAsync( List<String> accountIds, int maxResults) { logger.info("Starting usage totals paginator…"); ListUsageTotalsRequest.Builder builder = ListUsageTotalsRequest.builder() .maxResults(maxResults); if (accountIds != null && !accountIds.isEmpty()) { builder.accountIds(accountIds); } ListUsageTotalsRequest request = builder.build(); ListUsageTotalsPublisher paginator = getAsyncClient().listUsageTotalsPaginator(request); StringBuilder summaryBuilder = new StringBuilder(); return paginator.subscribe(response -> { if (response.totals() != null && !response.totals().isEmpty()) { response.totals().forEach(total -> { if (total.usage() != null) { total.usage().forEach(usage -> { logger.info("Usage: {} = {}", usage.typeAsString(), usage.total()); summaryBuilder.append(usage.typeAsString()) .append(": ") .append(usage.total()) .append("\n"); }); } }); } else { logger.info("Page contained no usage totals."); } }).thenRun(() -> logger.info("Successfully listed usage totals.")) .thenApply(v -> { String summary = summaryBuilder.toString(); return summary.isEmpty() ? "No usage totals found." : summary; }).exceptionally(ex -> { Throwable cause = ex.getCause() != null ? ex.getCause() : ex; if (cause instanceof ValidationException ve) { throw new CompletionException( "Validation error listing usage totals: %s".formatted(ve.getMessage()), ve ); } throw new CompletionException("Failed to list usage totals", cause); }); }
  • Para obtener más información sobre la API, consulta ListUsageTotalsla Referencia AWS SDK for Java 2.x de la API.