diff --git a/.doc_gen/metadata/inspector_metadata.yaml b/.doc_gen/metadata/inspector_metadata.yaml new file mode 100644 index 00000000000..aa5a4a3f507 --- /dev/null +++ b/.doc_gen/metadata/inspector_metadata.yaml @@ -0,0 +1,161 @@ +# zexi 0.4.2 +inspector_Hello: + title: Hello &Inspector; + title_abbrev: Hello &Inspector; + synopsis: get started using &Inspector;. + category: Hello + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.java2.hello.main + services: + inspector: {BatchGetAccountStatus, ListFindings, ListUsageTotals} +inspector_EnableInspector: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.java2.enable.main + services: + inspector: {Enable} +inspector_CreateFilter: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.java2.create.filter.main + services: + inspector: {CreateFilter} +inspector_GetAccountStatus: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.java2.get_account_status.main + services: + inspector: {BatchGetAccountStatus} +inspector_ListFindings: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.java2.list_findings.main + services: + inspector: {ListFindings} +inspector_BatchGetFindingDetails: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.java2.get_account_status.main + services: + inspector: {BatchGetFindingDetails} +inspector_ListCoverageStatistics: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.java2.list_coverage.stats.main + services: + inspector: {ListCoverageStatistics} +inspector_ListCoverage: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.java2.list_coverage.main + services: + inspector: {ListCoverage} +inspector_ListUsageTotals: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.java2.list_usage_totals.main + services: + inspector: {ListUsageTotals} +inspector_ListFilters: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.java2.list_filters.main + services: + inspector: {inspector_ListFilters} +inspector_Scenario: + synopsis_list: + - Check Inspector account status. + - Ensure Inspector is enabled. + - Analyze security findings. + - Check scan coverage. + - Create a findings filter. + - List existing filters. + - Check usage and costs. + - Get coverage statistics. + category: Basics + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: Run an interactive scenario demonstrating &Inspector; features. + snippet_tags: + - inspector.java2_scenario.main + - description: A wrapper class for &Inspector; SDK methods. + snippet_tags: + - inspector.java2_actions.main + services: + inspector: {} diff --git a/javav2/example_code/inspector/.gitignore b/javav2/example_code/inspector/.gitignore new file mode 100644 index 00000000000..5ff6309b719 --- /dev/null +++ b/javav2/example_code/inspector/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/javav2/example_code/inspector/pom.xml b/javav2/example_code/inspector/pom.xml new file mode 100644 index 00000000000..f559deabe0f --- /dev/null +++ b/javav2/example_code/inspector/pom.xml @@ -0,0 +1,118 @@ + + + 4.0.0 + + org.example + Inspector + 1.0-SNAPSHOT + + + UTF-8 + 17 + 17 + 17 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 21 + 21 + --enable-preview + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.2 + + + + + + + software.amazon.awssdk + bom + 2.29.45 + pom + import + + + org.apache.logging.log4j + log4j-bom + 2.23.1 + pom + import + + + + + + org.junit.jupiter + junit-jupiter + 5.11.4 + test + + + software.amazon.awssdk + netty-nio-client + + + software.amazon.awssdk + secretsmanager + + + com.google.code.gson + gson + 2.10.1 + + + com.fasterxml.jackson.core + jackson-databind + 2.17.0 + + + software.amazon.awssdk + inspector2 + + + software.amazon.awssdk + sso + + + software.amazon.awssdk + ssooidc + + + org.apache.logging.log4j + log4j-core + + + org.slf4j + slf4j-api + 2.0.13 + + + org.apache.logging.log4j + log4j-slf4j2-impl + + + software.amazon.awssdk + acm + + + org.apache.logging.log4j + log4j-1.2-api + + + software.amazon.awssdk + url-connection-client + 2.18.13 + + + \ No newline at end of file diff --git a/javav2/example_code/inspector/src/main/java/com/java/inspector/HelloInspector.java b/javav2/example_code/inspector/src/main/java/com/java/inspector/HelloInspector.java new file mode 100644 index 00000000000..bed9d6e69a4 --- /dev/null +++ b/javav2/example_code/inspector/src/main/java/com/java/inspector/HelloInspector.java @@ -0,0 +1,202 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.java.inspector; + +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.inspector2.Inspector2Client; +import software.amazon.awssdk.services.inspector2.model.BatchGetAccountStatusRequest; +import software.amazon.awssdk.services.inspector2.model.BatchGetAccountStatusResponse; +import software.amazon.awssdk.services.inspector2.model.AccountState; +import software.amazon.awssdk.services.inspector2.model.ResourceState; +import software.amazon.awssdk.services.inspector2.model.State; +import software.amazon.awssdk.services.inspector2.model.ListFindingsRequest; +import software.amazon.awssdk.services.inspector2.model.ListFindingsResponse; +import software.amazon.awssdk.services.inspector2.model.Finding; +import software.amazon.awssdk.services.inspector2.model.ListUsageTotalsRequest; +import software.amazon.awssdk.services.inspector2.model.ListUsageTotalsResponse; +import software.amazon.awssdk.services.inspector2.model.UsageTotal; +import software.amazon.awssdk.services.inspector2.model.Inspector2Exception; +import software.amazon.awssdk.services.inspector2.paginators.ListUsageTotalsIterable; +import java.util.List; +import java.util.ArrayList; + +// snippet-start:[inspector.java2.hello.main] +/** + * 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 { + + public static void main(String[] args) { + System.out.println(" Hello Amazon Inspector!"); + Region region = Region.US_EAST_1; + try (Inspector2Client inspectorClient = Inspector2Client.builder() + .region(region) + .build()) { + + System.out.println("Checking Inspector account status..."); + checkAccountStatus(inspectorClient); + System.out.println(); + + System.out.println("Checking for recent findings..."); + listRecentFindings(inspectorClient); + System.out.println(); + + System.out.println("Checking usage totals..."); + showUsageTotals(inspectorClient); + System.out.println(); + + System.out.println("Hello Inspector example completed successfully!"); + + } catch (Inspector2Exception e) { + System.err.println(" Error: " + e.getMessage()); + System.err.println(" Troubleshooting:"); + System.err.println("1. Verify AWS credentials are configured"); + System.err.println("2. Check IAM permissions for Inspector2"); + System.err.println("3. Ensure Inspector2 is enabled in your account"); + System.err.println("4. Verify you're using a supported region"); + } + } + + /** + * Checks the account status using the provided Inspector2Client. + * This method sends a request to retrieve the account status and prints the details of each account's resource states. + * + * @param inspectorClient The Inspector2Client used to interact with the AWS Inspector service. + */ + public static void checkAccountStatus(Inspector2Client inspectorClient) { + try { + BatchGetAccountStatusRequest request = BatchGetAccountStatusRequest.builder().build(); + BatchGetAccountStatusResponse response = inspectorClient.batchGetAccountStatus(request); + + List accounts = response.accounts(); + if (accounts == null || accounts.isEmpty()) { + System.out.println(" No account information returned."); + return; + } + + for (AccountState account : accounts) { + System.out.println(" Account: " + account.accountId()); + ResourceState resources = account.resourceState(); + if (resources == null) { + System.out.println(" No resource state data available."); + continue; + } + + System.out.println(" Resource States:"); + printState("EC2", resources.ec2()); + printState("ECR", resources.ecr()); + printState("Lambda", resources.lambda()); + printState("Lambda Code", resources.lambdaCode()); + System.out.println(); + } + + } catch (Inspector2Exception e) { + System.err.println(" Failed to retrieve account status: " + e.awsErrorDetails().errorMessage()); + } + } + + public static void printState(String name, State state) { + if (state == null) { + System.out.println(" - " + name + ": (no data)"); + return; + } + String err = state.errorMessage() != null ? " (Error: " + state.errorMessage() + ")" : ""; + System.out.println(" - " + name + ": " + state.status() + err); + } + + /** + * Retrieves and prints the most recent findings from the Inspector2 service. + * + * @param inspectorClient the Inspector2Client used to interact with the AWS Inspector2 service + */ + public static void listRecentFindings(Inspector2Client inspectorClient) { + try { + ListFindingsRequest request = ListFindingsRequest.builder() + .maxResults(10) + .build(); + + ListFindingsResponse response = inspectorClient.listFindings(request); + List findings = response.findings(); + + if (findings == null || findings.isEmpty()) { + System.out.println(" No findings found."); + } else { + System.out.println(" Found " + findings.size() + " recent finding(s):"); + for (Finding finding : findings) { + System.out.println(" Title: " + finding.title()); + System.out.println(" Severity: " + finding.severity()); + System.out.println(" Status: " + finding.status()); + System.out.println(" Last Observed: " + finding.lastObservedAt()); + System.out.println(); + } + } + + } catch (Inspector2Exception e) { + System.err.println(" Error listing findings: " + e.awsErrorDetails().errorMessage()); + } + } + + /** + * Displays the usage totals for the Inspector2 service. + * + * @param inspectorClient the {@code Inspector2Client} used to make the API call to + * retrieve the usage totals. + * + * @throws Inspector2Exception if there is an error while retrieving the usage totals. + * The error message is printed to the standard error output. + */ + public static void showUsageTotals(Inspector2Client inspectorClient) { + try { + System.out.println("Listing usage totals using paginator..."); + ListUsageTotalsRequest request = ListUsageTotalsRequest.builder() + .maxResults(10) + .build(); + + // Create paginator. + ListUsageTotalsIterable paginator = inspectorClient.listUsageTotalsPaginator(request); + List allTotals = new ArrayList<>(); + + // Iterate through all pages. + for (ListUsageTotalsResponse response : paginator) { + List totals = response.totals(); + if (totals != null && !totals.isEmpty()) { + allTotals.addAll(totals); + } + } + + // Display results. + if (allTotals.isEmpty()) { + System.out.println(" No usage data available yet."); + System.out.println(" Usage data appears after Inspector has been active for some time."); + } else { + System.out.println(" Usage Totals (Last 30 days):"); + for (UsageTotal total : allTotals) { + System.out.println(" Account: " + total.accountId()); + if (total.usage() != null && !total.usage().isEmpty()) { + total.usage().forEach(u -> { + System.out.println(" - " + u.type() + ": " + u.total()); + if (u.estimatedMonthlyCost() != null) { + System.out.println(" Estimated Monthly Cost: " + + u.estimatedMonthlyCost() + " " + u.currency()); + } + }); + } + System.out.println(); + } + } + + } catch (Inspector2Exception e) { + System.err.println(" Error getting usage totals: " + e.awsErrorDetails().errorMessage()); + throw e; + } catch (Exception e) { + throw new RuntimeException("Unexpected error while listing usage totals: " + e.getMessage(), e); + } + } +} +// snippet-end:[inspector.java2.hello.main] diff --git a/javav2/example_code/inspector/src/main/java/com/java/inspector/InspectorActions.java b/javav2/example_code/inspector/src/main/java/com/java/inspector/InspectorActions.java new file mode 100644 index 00000000000..9aa1967fb30 --- /dev/null +++ b/javav2/example_code/inspector/src/main/java/com/java/inspector/InspectorActions.java @@ -0,0 +1,491 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.java.inspector; + +import software.amazon.awssdk.services.inspector2.Inspector2Client; +import software.amazon.awssdk.services.inspector2.model.*; +import software.amazon.awssdk.services.inspector2.paginators.ListCoverageIterable; +import software.amazon.awssdk.services.inspector2.paginators.ListCoverageStatisticsIterable; +import software.amazon.awssdk.services.inspector2.paginators.ListFiltersIterable; +import software.amazon.awssdk.services.inspector2.paginators.ListUsageTotalsIterable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +// snippet-start:[inspector.java2_actions.main] +public class InspectorActions { + + // snippet-start:[inspector.java2.enable.main] + /** + * Enables AWS Inspector for the provided account(s) and default resource types. + * + * @param inspectorClient The Inspector2 client. + * @param accountIds Optional list of AWS account IDs. + */ + public void enableInspector(Inspector2Client inspectorClient, List accountIds) { + + // Default resource types to enable. + List resourceTypes = List.of( + ResourceScanType.EC2, + ResourceScanType.ECR, + ResourceScanType.LAMBDA, + ResourceScanType.LAMBDA_CODE + ); + + EnableRequest.Builder requestBuilder = EnableRequest.builder() + .resourceTypes(resourceTypes); + + if (accountIds != null && !accountIds.isEmpty()) { + requestBuilder.accountIds(accountIds); + } + + EnableRequest request = requestBuilder.build(); + try { + EnableResponse response = inspectorClient.enable(request); + + if (response.accounts() != null && !response.accounts().isEmpty()) { + System.out.println("Inspector enable operation results:"); + for (Account account : response.accounts()) { + String accountId = account.accountId() != null ? account.accountId() : "Unknown"; + String status = account.status() != null ? account.statusAsString() : "Unknown"; + System.out.println(" • Account: " + accountId + " → Status: " + status); + } + } else { + System.out.println(" Inspector may already be enabled for all target accounts."); + } + + } catch (ValidationException ve) { + System.out.println(" Inspector may already be enabled for this account: " + ve.getMessage()); + + } catch (Inspector2Exception e) { + System.err.println("AWS Inspector2 service error: " + e.awsErrorDetails().errorMessage()); + throw e; + } catch (Exception e) { + throw new RuntimeException("Failed to enable Inspector: " + e.getMessage(), e); + } + } + // snippet-end:[inspector.java2.enable.main] + + // snippet-start:[inspector.java2.list_coverage.stats.main] + /** + * Retrieves and prints the coverage statistics using a paginator. + * + * @param inspectorClient the Inspector2Client used to retrieve the coverage statistics + */ + public void listCoverageStatistics(Inspector2Client inspectorClient) { + try { + System.out.println("Listing coverage statistics using paginator..."); + ListCoverageStatisticsRequest request = ListCoverageStatisticsRequest.builder() + .build(); + + // Create paginator. + ListCoverageStatisticsIterable paginator = inspectorClient.listCoverageStatisticsPaginator(request); + List allCounts = new ArrayList<>(); + + // Iterate through all pages. + for (ListCoverageStatisticsResponse response : paginator) { + List counts = response.countsByGroup(); + if (counts != null && !counts.isEmpty()) { + allCounts.addAll(counts); + } + } + + // Display results. + if (allCounts.isEmpty()) { + System.out.println("No coverage statistics available"); + } else { + System.out.println("Coverage Statistics:"); + for (Counts count : allCounts) { + System.out.println(" Group: " + count.groupKey()); + System.out.println(" Total Count: " + count.count()); + System.out.println(); + } + } + + } catch (ValidationException ve) { + System.out.println(" Validation error: " + ve.getMessage()); + System.out.println(" This likely means there are no coverage statistics available at this time."); + + } catch (Inspector2Exception e) { + System.err.println(" AWS Inspector2 service error: " + e.awsErrorDetails().errorMessage()); + throw e; + + } catch (Exception e) { + throw new RuntimeException("Failed to list coverage statistics: " + e.getMessage(), e); + } + } + // snippet-end:[inspector.java2.list_coverage.stats.main] + + // snippet-start:[inspector.java2.list_usage_totals.main] + /** + * Retrieves and prints the usage totals for the specified accounts using a paginator. + * + * @param inspectorClient the Inspector2Client used to make the API call + * @param accountIds a list of account IDs for which to retrieve usage totals. If null or empty, all accounts are considered. + * @param maxResults the maximum number of results to return + */ + public void listUsageTotals( + Inspector2Client inspectorClient, + List accountIds, + int maxResults + ) { + try { + System.out.println("Listing usage totals using paginator..."); + ListUsageTotalsRequest.Builder requestBuilder = ListUsageTotalsRequest.builder() + .maxResults(maxResults); + + if (accountIds != null && !accountIds.isEmpty()) { + requestBuilder.accountIds(accountIds); + } + + ListUsageTotalsRequest request = requestBuilder.build(); + + // Create paginator. + ListUsageTotalsIterable paginator = inspectorClient.listUsageTotalsPaginator(request); + + List allTotals = new ArrayList<>(); + for (ListUsageTotalsResponse response : paginator) { + List totals = response.totals(); + if (totals != null && !totals.isEmpty()) { + allTotals.addAll(totals); + } + } + + // Display results. + if (allTotals.isEmpty()) { + System.out.println("No usage data available yet"); + System.out.println("Usage data appears after Inspector has been active for some time"); + } else { + System.out.println("Usage Totals (Last 30 days):"); + for (UsageTotal total : allTotals) { + System.out.println(" Account: " + total.accountId()); + List usageList = total.usage(); + + if (usageList != null && !usageList.isEmpty()) { + for (Usage usage : usageList) { + System.out.println(" - " + usage.type() + ": " + usage.total()); + if (usage.estimatedMonthlyCost() != null) { + System.out.println(" Estimated Monthly Cost: " + + usage.estimatedMonthlyCost() + " " + usage.currency()); + } + } + } + System.out.println(); + } + } + + } catch (ValidationException ve) { + System.out.println(" Validation error: " + ve.getMessage()); + System.out.println(" This likely means there is no usage data available for the provided accounts."); + + } catch (Inspector2Exception e) { + System.err.println(" AWS Inspector2 service error: " + e.awsErrorDetails().errorMessage()); + throw e; + + } catch (Exception e) { + throw new RuntimeException("Failed to list usage totals: " + e.getMessage(), e); + } + } + // snippet-end:[inspector.java2.list_usage_totals.main] + + // snippet-start:[inspector.java2.get_account_status.main] + /** + * Retrieves the account status using the Inspector2Client. + * + * @param inspectorClient the Inspector2Client used to send the request and retrieve the account status + */ + public void getAccountStatus(Inspector2Client inspectorClient) { + BatchGetAccountStatusRequest request = BatchGetAccountStatusRequest.builder() + .accountIds(Collections.emptyList()) // current account + .build(); + + BatchGetAccountStatusResponse response = inspectorClient.batchGetAccountStatus(request); + if (response.accounts() != null) { + for (AccountState account : response.accounts()) { + String state = (account.state() != null && account.state().status() != null) + ? String.valueOf(account.state().status()) + : "Unknown"; + System.out.println("Account: " + account.accountId() + ", State: " + state); + } + } + + System.out.println("Inspector Account Status:"); + if (response.accounts() != null) { + for (AccountState account : response.accounts()) { + System.out.println(" Account ID: " + (account.accountId() != null ? account.accountId() : "Unknown")); + + // Resource state (only status is available) + ResourceState resources = account.resourceState(); + if (resources != null) { + System.out.println(" Resource Status error: "); + } + + // Overall account state. + if (account.state() != null && account.state().status() != null) { + System.out.println(" Overall State: " + account.state().status()); + } + } + } + } + // snippet-end:[inspector.java2.get_account_status.main] + + // snippet-start:[inspector.java2.list_filters.main] + /** + * Retrieves a list of filters using a paginator. + * + * @param inspector2Client An instance of {@code Inspector2Client} used to interact with AWS Inspector2. + * @param maxResults The maximum number of filters to return. If null, the default maximum results will be used. + * + * @throws Inspector2Exception If an error occurs specific to AWS Inspector2, such as invalid parameters or service issues. + */ + public void listFilters(Inspector2Client inspector2Client, Integer maxResults) { + try { + System.out.println("Listing filters using paginator..."); + ListFiltersRequest.Builder requestBuilder = ListFiltersRequest.builder(); + if (maxResults != null) { + requestBuilder.maxResults(maxResults); + } + + // Create paginator. + ListFiltersIterable paginator = inspector2Client.listFiltersPaginator(requestBuilder.build()); + int totalCount = 0; + + // Iterate over pages. + for (var response : paginator) { + List filters = response.filters(); + if (filters == null || filters.isEmpty()) { + continue; + } + + for (Filter filter : filters) { + totalCount++; + System.out.println(" - " + filter.name()); + System.out.println(" ARN: " + filter.arn()); + System.out.println(" Action: " + filter.action()); + System.out.println(" Owner: " + filter.ownerId()); + System.out.println(" Created: " + filter.createdAt()); + System.out.println(); + } + } + + if (totalCount == 0) { + System.out.println(" No filters found."); + } else { + System.out.println(" Found " + totalCount + " filter(s) in total."); + } + + } catch (Inspector2Exception e) { + System.err.println("Failed to list filters: " + e.awsErrorDetails().errorMessage()); + throw e; + } catch (Exception e) { + System.err.println("Unexpected error: " + e.getMessage()); + throw e; + } + } + // snippet-end:[inspector.java2.list_filters.main] + + // snippet-start:[inspector.java2.create.filter.main] + /** + * Creates a new filter in AWS Inspector2 to suppress findings of low severity. + * + * @param inspector2Client An instance of {@code Inspector2Client} used to interact with AWS Inspector2. + * @param description A descriptive string that explains the purpose of the filter. + * + * + * @throws Inspector2Exception If an error occurs specific to AWS Inspector2, such as invalid parameters or service issues. + * @throws Exception If an unexpected error occurs during the filter creation process. + * + */ + public void createFilter(Inspector2Client inspector2Client, String description) { + String filterName = "suppress-low-severity-" + System.currentTimeMillis(); + System.out.println("Creating filter: " + filterName); + + try { + // Define a filter to match LOW severity findings. + StringFilter severityFilter = StringFilter.builder() + .value(Severity.LOW.toString()) + .comparison(StringComparison.EQUALS) + .build(); + + // Create filter criteria using the severity filter. + FilterCriteria filterCriteria = FilterCriteria.builder() + .severity(Collections.singletonList(severityFilter)) + .build(); + + // Build the filter creation request. + CreateFilterRequest createRequest = CreateFilterRequest.builder() + .name(filterName) + .filterCriteria(filterCriteria) + .action(FilterAction.SUPPRESS) + .description(description) + .build(); + + // Execute the request. + CreateFilterResponse response = inspector2Client.createFilter(createRequest); + System.out.println("Successfully created filter with ARN: " + response.arn()); + + } catch (Inspector2Exception e) { + System.err.println("Failed to create filter: " + e.awsErrorDetails().errorMessage()); + throw e; + } catch (Exception e) { + System.err.println("Unexpected error: " + e.getMessage()); + throw e; + } + } + // snippet-end:[inspector.java2.create.filter.main] + + // snippet-start:[inspector.java2.list_findings.main] + /** + * Lists findings from AWS Inspector2 . + * + * @param inspectorClient The Inspector2 client. + * @param maxResults Maximum number of results to retrieve. + * @param filterCriteria Optional filter criteria (can be null). + */ + public void listFindings( + Inspector2Client inspectorClient, + int maxResults, + FilterCriteria filterCriteria + ) { + // Build the request + ListFindingsRequest.Builder requestBuilder = ListFindingsRequest.builder() + .maxResults(maxResults); + + if (filterCriteria != null) { + requestBuilder.filterCriteria(filterCriteria); + } + + ListFindingsRequest request = requestBuilder.build(); + try { + ListFindingsResponse findingsResponse = inspectorClient.listFindings(request); + List findings = findingsResponse.findings(); + + if (findings == null || findings.isEmpty()) { + System.out.println(" No findings found"); + System.out.println(" This could mean:"); + System.out.println(" • Inspector hasn't completed its initial scan yet"); + System.out.println(" • Your resources don't have any vulnerabilities"); + System.out.println(" • All findings have been suppressed by filters"); + } else { + System.out.println(" Found " + findings.size() + " finding(s):"); + Map> findingsBySeverity = findings.stream() + .collect(Collectors.groupingBy(f -> f.severityAsString())); + + for (Map.Entry> entry : findingsBySeverity.entrySet()) { + System.out.println(" " + entry.getKey() + ": " + entry.getValue().size() + " finding(s)"); + } + + System.out.println(); + System.out.println(" Recent findings:"); + for (int i = 0; i < Math.min(findings.size(), 5); i++) { + Finding finding = findings.get(i); + System.out.println(" " + (i + 1) + ". " + finding.title()); + System.out.println(" Type: " + finding.type()); + System.out.println(" Severity: " + finding.severityAsString()); + System.out.println(" Status: " + finding.statusAsString()); + + if (finding.resources() != null && !finding.resources().isEmpty()) { + Resource resource = finding.resources().get(0); + System.out.println(" Resource: " + resource.typeAsString() + " - " + resource.id()); + } + + if (finding.inspectorScore() != null) { + System.out.println(" Inspector Score: " + finding.inspectorScore()); + } + System.out.println(); + } + } + + } catch (ValidationException ve) { + System.out.println(" Validation error: " + ve.getMessage()); + + } catch (Inspector2Exception e) { + System.err.println("AWS Inspector2 service error: " + e.awsErrorDetails().errorMessage()); + throw e; + + } catch (Exception e) { + throw new RuntimeException("Failed to list findings: " + e.getMessage(), e); + } + } + // snippet-end:[inspector.java2.list_findings.main] + + // snippet-start:[inspector.java2.list_coverage.main] + /** + * Lists AWS Inspector2 coverage details for scanned resources using a paginator. + * + * @param inspectorClient The Inspector2 client. + * @param maxResults Maximum number of resources to return. + */ + public void listCoverage(Inspector2Client inspectorClient, int maxResults) { + try { + System.out.println("Listing coverage information using paginator..."); + ListCoverageRequest request = ListCoverageRequest.builder() + .maxResults(maxResults) + .build(); + + // Create paginator. + ListCoverageIterable paginator = inspectorClient.listCoveragePaginator(request); + List allCoveredResources = new ArrayList<>(); + + // Iterate through all pages. + for (ListCoverageResponse response : paginator) { + List coveredResources = response.coveredResources(); + if (coveredResources != null && !coveredResources.isEmpty()) { + allCoveredResources.addAll(coveredResources); + } + } + + if (allCoveredResources.isEmpty()) { + System.out.println(" No coverage information available."); + System.out.println(" This likely means Inspector hasn't yet scanned your resources or no supported resource types are present."); + return; + } + + System.out.println(" Coverage Information:"); + System.out.println(" Total resources covered: " + allCoveredResources.size()); + + // Group by resource type. + Map> resourcesByType = allCoveredResources.stream() + .collect(Collectors.groupingBy(CoveredResource::resourceTypeAsString)); + + for (Map.Entry> entry : resourcesByType.entrySet()) { + System.out.println(" " + entry.getKey() + ": " + entry.getValue().size() + " resource(s)"); + } + + System.out.println(); + System.out.println(" Sample covered resources:"); + + // Display up to 3 sample resources. + for (int i = 0; i < Math.min(allCoveredResources.size(), 3); i++) { + CoveredResource resource = allCoveredResources.get(i); + System.out.println(" - " + resource.resourceTypeAsString() + ": " + resource.resourceId()); + System.out.println(" Scan Type: " + resource.scanTypeAsString()); + + if (resource.scanStatus() != null) { + System.out.println(" Status: " + resource.scanStatus().statusCodeAsString()); + } + + if (resource.accountId() != null) { + System.out.println(" Account ID: " + resource.accountId()); + } + System.out.println(); + } + + } catch (ValidationException ve) { + System.out.println(" Validation error: " + ve.getMessage()); + System.out.println(" This likely means no resources are currently covered by Inspector2."); + + } catch (Inspector2Exception e) { + System.err.println(" AWS Inspector2 service error: " + e.awsErrorDetails().errorMessage()); + throw e; + + } catch (Exception e) { + throw new RuntimeException("Failed to list coverage: " + e.getMessage(), e); + } + } + // snippet-end:[inspector.java2.list_coverage.main] +} +// snippet-end:[inspector.java2_actions.main] \ No newline at end of file diff --git a/javav2/example_code/inspector/src/main/java/com/java/inspector/InspectorScenario.java b/javav2/example_code/inspector/src/main/java/com/java/inspector/InspectorScenario.java new file mode 100644 index 00000000000..c145cee420f --- /dev/null +++ b/javav2/example_code/inspector/src/main/java/com/java/inspector/InspectorScenario.java @@ -0,0 +1,198 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.java.inspector; + +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.inspector2.Inspector2Client; +import java.util.Scanner; + +// snippet-start:[inspector.java2_scenario.main] +/** + * 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 InspectorScenario { + public static final String DASHES = new String(new char[80]).replace("\0", "-"); + + static Scanner scanner = new Scanner(System.in); + public static void main(String[] args) { + + InspectorActions inspectorActions = new InspectorActions(); + + Inspector2Client inspectorClient = Inspector2Client.builder() + .region(Region.US_EAST_1) + .build() ; + + System.out.println("🔍 Amazon Inspector Basics Scenario"); + System.out.println(DASHES); + System.out.println(); + + System.out.println(""" + 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(scanner); + + // Step 1: Check current account status. + System.out.println(DASHES); + System.out.println("Step 1: Checking Inspector account status..."); + + try { + inspectorActions.getAccountStatus(inspectorClient); + + } catch (Exception e) { + System.err.println(" Could not create example filter: " + e.getMessage()); + } + waitForInputToContinue(scanner); + + // Step 2: Enable Inspector for resource types (if not already enabled). + System.out.println(DASHES); + System.out.println("Step 2: Ensuring Inspector is enabled..."); + + try { + inspectorActions.enableInspector(inspectorClient, null); + + } catch (Exception e) { + System.err.println(" Could not create example filter: " + e.getMessage()); + } + waitForInputToContinue(scanner); + + // Step 3: List and analyze findings. + System.out.println(DASHES); + System.out.println("Step 3: Analyzing security findings..."); + int maxResults = 10; + + try { + inspectorActions.listFindings(inspectorClient, maxResults, null); + + } catch (Exception e) { + System.err.println(" Could not create example filter: " + e.getMessage()); + } + System.out.println(); + waitForInputToContinue(scanner); + + // Step 4: Show coverage information. + System.out.println(DASHES); + System.out.println("Step 4: Checking scan coverage..."); + maxResults = 5; + + try { + inspectorActions.listCoverage(inspectorClient, maxResults); + + } catch (Exception e) { + System.err.println(" Could not create example filter: " + e.getMessage()); + } + System.out.println(); + waitForInputToContinue(scanner); + + // Step 5: Create a findings filter (example) + System.out.println(DASHES); + System.out.println("Step 5: Creating a findings filter..."); + try { + inspectorActions.createFilter( + inspectorClient, + "Suppress low severity findings for demo purposes" + ); + + System.out.println("Created example filter"); + + } catch (Exception e) { + System.err.println(" Could not create example filter: " + e.getMessage()); + } + System.out.println(); + waitForInputToContinue(scanner); + + // Step 6: List existing filters + System.out.println(DASHES); + System.out.println("Step 6: Listing existing filters..."); + + try { + inspectorActions.listFilters(inspectorClient, 10); + + } catch (Exception e) { + System.err.println(" Could not create example filter: " + e.getMessage()); + } + System.out.println(); + waitForInputToContinue(scanner); + + // Step 7: Show usage totals + System.out.println(DASHES); + System.out.println("Step 7: Checking usage and costs..."); + + try { + inspectorActions.listUsageTotals(inspectorClient, null, 10); + } catch (Exception e) { + System.err.println(" Could not create example filter: " + e.getMessage()); + } + + System.out.println(); + waitForInputToContinue(scanner); + + // Step 8: Coverage statistics + System.out.println(DASHES); + System.out.println("Step 8: Getting coverage statistics..."); + + try{ + inspectorActions.listCoverageStatistics(inspectorClient); + } catch (Exception e) { + System.err.println(" Could not create example filter: " + e.getMessage()); + } + System.out.println(); + + System.out.println("🎉 Inspector Basics scenario completed successfully!"); + System.out.println(); + System.out.println("📚 What you learned:"); + System.out.println(" ✓ How to check Inspector account status and configuration"); + System.out.println(" ✓ How to enable Inspector for different resource types"); + System.out.println(" ✓ How to list and analyze security findings"); + System.out.println(" ✓ How to monitor scan coverage across your resources"); + System.out.println(" ✓ How to create filters to suppress findings"); + System.out.println(" ✓ How to track usage and costs"); + System.out.println(); + System.out.println("🔗 Next steps:"); + System.out.println(" • Set up EventBridge rules to respond to findings"); + System.out.println(" • Create custom filters for your environment"); + System.out.println(" • Generate detailed findings reports"); + System.out.println(" • Integrate with AWS Security Hub"); + waitForInputToContinue(scanner); + + System.out.println(); + System.out.println(" This concludes the AWS Inspector Service scenario."); + } + + + private static void waitForInputToContinue(Scanner scanner) { + while (true) { + System.out.println(""); + System.out.println("Enter 'c' followed by to continue:"); + String input = scanner.nextLine(); + + if (input.trim().equalsIgnoreCase("c")) { + System.out.println("Continuing with the program..."); + System.out.println(""); + break; + } else { + System.out.println("Invalid input. Please try again."); + } + } + } +} +// snippet-end:[inspector.java2_scenario.main] \ No newline at end of file diff --git a/javav2/example_code/inspector/src/test/java/InspectorTests.java b/javav2/example_code/inspector/src/test/java/InspectorTests.java new file mode 100644 index 00000000000..b4f2620ecf8 --- /dev/null +++ b/javav2/example_code/inspector/src/test/java/InspectorTests.java @@ -0,0 +1,64 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import com.java.inspector.HelloInspector; +import com.java.inspector.InspectorActions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.inspector2.Inspector2Client; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +@TestInstance(TestInstance.Lifecycle.PER_METHOD) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class InspectorTests { + private static Inspector2Client inspector; + private static InspectorActions inspectorActions; + + @BeforeAll + public static void setUp() { + inspector = Inspector2Client.builder() + .region(Region.US_EAST_1) + .build() ; + + inspectorActions = new InspectorActions(); + } + + @Test + @Tag("IntegrationTest") + @Order(1) + public void testHelloService() { + assertDoesNotThrow(() -> { + HelloInspector.checkAccountStatus(inspector); + HelloInspector.listRecentFindings(inspector); + HelloInspector.showUsageTotals(inspector); + }); + System.out.println("Test 1 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(2) + public void testScenario() { + assertDoesNotThrow(() -> { + int maxResults = 10; + inspectorActions.getAccountStatus(inspector); + inspectorActions.enableInspector(inspector, null); + + inspectorActions.listFindings(inspector, maxResults, null); + maxResults = 5; + inspectorActions.listCoverage(inspector, maxResults); + + inspectorActions.createFilter(inspector, "Suppress low severity findings for demo purposes"); + inspectorActions.listFilters(inspector, 10); + inspectorActions.listUsageTotals(inspector, null, 10); + inspectorActions.listCoverageStatistics(inspector); + }); + System.out.println("Test 2 passed"); + } +} diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index 252a707c8e8..37b8ac9e223 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -9,7 +9,6 @@ import software.amazon.awssdk.services.iotsitewise.model.AssetModelPropertySummary; import software.amazon.awssdk.services.iotsitewise.model.BatchPutAssetPropertyValueResponse; import software.amazon.awssdk.services.iotsitewise.model.CreateGatewayRequest; -import software.amazon.awssdk.services.iotsitewise.model.CreateGatewayResponse; import software.amazon.awssdk.services.iotsitewise.model.DeleteGatewayRequest; import software.amazon.awssdk.services.iotsitewise.model.DeleteGatewayResponse; import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayRequest;