From ebd3e2efbd014043182392b91b39dd459d425119 Mon Sep 17 00:00:00 2001 From: Macdonald Date: Mon, 27 Oct 2025 11:40:02 -0400 Subject: [PATCH 01/11] Add inspector files --- javav2/example_code/inspector/.gitignore | 38 +++ javav2/example_code/inspector/pom.xml | 118 +++++++ .../com/java/inspector/HelloInspector.java | 153 +++++++++ .../com/java/inspector/InspectorActions.java | 186 +++++++++++ .../com/java/inspector/InspectorScenario.java | 311 ++++++++++++++++++ 5 files changed, 806 insertions(+) create mode 100644 javav2/example_code/inspector/.gitignore create mode 100644 javav2/example_code/inspector/pom.xml create mode 100644 javav2/example_code/inspector/src/main/java/com/java/inspector/HelloInspector.java create mode 100644 javav2/example_code/inspector/src/main/java/com/java/inspector/InspectorActions.java create mode 100644 javav2/example_code/inspector/src/main/java/com/java/inspector/InspectorScenario.java 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..634bd59c3a7 --- /dev/null +++ b/javav2/example_code/inspector/src/main/java/com/java/inspector/HelloInspector.java @@ -0,0 +1,153 @@ +package com.java.inspector; + +import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; +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 java.util.List; + +public class HelloInspector { + + public static void main(String[] args) { + System.out.println("🔍 Hello Amazon Inspector!"); + System.out.println("========================================\n"); + + 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"); + } + } + + // ✅ Fixed version using BatchGetAccountStatus + private 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()); + } + } + + private 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); + } + + private 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()); + } + } + + private static void showUsageTotals(Inspector2Client inspectorClient) { + try { + ListUsageTotalsRequest request = ListUsageTotalsRequest.builder() + .maxResults(10) + .build(); + + ListUsageTotalsResponse response = inspectorClient.listUsageTotals(request); + List totals = response.totals(); + + if (totals == null || totals.isEmpty()) { + System.out.println("📊 No usage data available yet."); + } else { + System.out.println("✅ Usage Totals (Last 30 days):"); + for (UsageTotal total : totals) { + System.out.println(" Account: " + total.accountId()); + total.usage().forEach(u -> + System.out.println(" - " + u.type() + ": " + u.total() + + " (Est. Monthly: " + u.estimatedMonthlyCost() + " " + u.currency() + ")")); + System.out.println(); + } + } + + } catch (Inspector2Exception e) { + System.err.println("❌ Error getting usage totals: " + e.awsErrorDetails().errorMessage()); + } + } +} + 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..a951f8104d1 --- /dev/null +++ b/javav2/example_code/inspector/src/main/java/com/java/inspector/InspectorActions.java @@ -0,0 +1,186 @@ +package com.java.inspector; + +import software.amazon.awssdk.services.inspector2.Inspector2Client; +import software.amazon.awssdk.services.inspector2.model.*; + +import java.util.Collections; +import java.util.List; + +public class InspectorActions { + + // ---------------------- ENABLE INSPECTOR ---------------------- + public EnableResponse enableInspector( + Inspector2Client inspectorClient, + List resourceTypes, + List accountIds // can be null + ) { + 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); + System.out.println("✅ Inspector enable request completed"); + + if (response.accounts() != null) { + 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); + } + } + + return response; + + } catch (Exception e) { + System.err.println("❌ Failed to enable Inspector: " + e.getMessage()); + throw e; + } + } + + // ---------------------- COVERAGE STATISTICS ---------------------- + public static ListCoverageStatisticsResponse listCoverageStatistics(Inspector2Client inspectorClient) { + ListCoverageStatisticsRequest request = ListCoverageStatisticsRequest.builder() + .build(); + + return inspectorClient.listCoverageStatistics(request); + } + + // ---------------------- LIST USAGE TOTALS ---------------------- + public ListUsageTotalsResponse listUsageTotals( + Inspector2Client inspectorClient, + List accountIds, + int maxResults + ) { + ListUsageTotalsRequest.Builder requestBuilder = ListUsageTotalsRequest.builder() + .maxResults(maxResults); + + if (accountIds != null && !accountIds.isEmpty()) { + requestBuilder.accountIds(accountIds); + } + + ListUsageTotalsRequest request = requestBuilder.build(); + return inspectorClient.listUsageTotals(request); + } + + // ---------------------- ACCOUNT STATUS ---------------------- + public BatchGetAccountStatusResponse 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); + } + } + + return response; + } + + // ---------------------- LIST FILTERS ---------------------- + public static ListFiltersResponse listFilters( + Inspector2Client inspector2Client, + Integer maxResults + ) { + try { + System.out.println("Listing filters"); + + ListFiltersRequest.Builder requestBuilder = ListFiltersRequest.builder(); + if (maxResults != null) { + requestBuilder.maxResults(maxResults); + } + + ListFiltersResponse response = inspector2Client.listFilters(requestBuilder.build()); + + int count = response.filters() != null ? response.filters().size() : 0; + System.out.println("Successfully listed filters: " + count); + return response; + + } catch (Inspector2Exception e) { + System.out.println("Failed to list filters: " + e.getMessage()); + throw e; + } + } + + // ---------------------- CREATE FILTER ---------------------- + public static CreateFilterResponse createFilter( + Inspector2Client inspector2Client, + String description + ) { + try { + String filterName = "suppress-low-severity-" + System.currentTimeMillis(); + System.out.println("Creating filter: " + filterName); + + // Build severity filter + StringFilter severityFilter = StringFilter.builder() + .value(Severity.LOW.toString()) + .comparison(StringComparison.EQUALS) + .build(); + + FilterCriteria filterCriteria = FilterCriteria.builder() + .severity(List.of(severityFilter)) + .build(); + + CreateFilterRequest createRequest = CreateFilterRequest.builder() + .name(filterName) + .filterCriteria(filterCriteria) + .action(FilterAction.SUPPRESS) + .description(description) + .build(); + + CreateFilterResponse response = inspector2Client.createFilter(createRequest); + System.out.println("✅ Successfully created filter with ARN: " + response.arn()); + return response; + + } 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; + } + } + + // ---------------------- LIST FINDINGS ---------------------- + public ListFindingsResponse listFindings( + Inspector2Client inspectorClient, + int maxResults, + FilterCriteria filterCriteria // can be null + ) { + ListFindingsRequest.Builder requestBuilder = ListFindingsRequest.builder() + .maxResults(maxResults); + + if (filterCriteria != null) { + requestBuilder.filterCriteria(filterCriteria); + } + + ListFindingsRequest request = requestBuilder.build(); + ListFindingsResponse response = inspectorClient.listFindings(request); + + List findings = response.findings(); + int count = findings != null ? findings.size() : 0; + System.out.println("✅ Listed " + count + " findings"); + + return response; + } + + // ---------------------- LIST COVERAGE ---------------------- + public ListCoverageResponse listCoverage(Inspector2Client inspectorClient, int maxResults) { + ListCoverageRequest request = ListCoverageRequest.builder() + .maxResults(maxResults) + .build(); + + return inspectorClient.listCoverage(request); + } +} 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..529560f466f --- /dev/null +++ b/javav2/example_code/inspector/src/main/java/com/java/inspector/InspectorScenario.java @@ -0,0 +1,311 @@ +package com.java.inspector; + + +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.inspector2.Inspector2Client; +import software.amazon.awssdk.services.inspector2.model.AccountState; +import software.amazon.awssdk.services.inspector2.model.BatchGetAccountStatusResponse; +import software.amazon.awssdk.services.inspector2.model.Counts; +import software.amazon.awssdk.services.inspector2.model.CoveredResource; +import software.amazon.awssdk.services.inspector2.model.CreateFilterResponse; +import software.amazon.awssdk.services.inspector2.model.Filter; +import software.amazon.awssdk.services.inspector2.model.FilterAction; +import software.amazon.awssdk.services.inspector2.model.FilterCriteria; +import software.amazon.awssdk.services.inspector2.model.Finding; +import software.amazon.awssdk.services.inspector2.model.ListCoverageResponse; +import software.amazon.awssdk.services.inspector2.model.ListCoverageStatisticsResponse; +import software.amazon.awssdk.services.inspector2.model.ListFiltersResponse; +import software.amazon.awssdk.services.inspector2.model.ListFindingsResponse; +import software.amazon.awssdk.services.inspector2.model.ListUsageTotalsResponse; +import software.amazon.awssdk.services.inspector2.model.Resource; +import software.amazon.awssdk.services.inspector2.model.ResourceScanType; +import software.amazon.awssdk.services.inspector2.model.ResourceState; +import software.amazon.awssdk.services.inspector2.Inspector2Client; +import software.amazon.awssdk.services.inspector2.model.AccountState; +import software.amazon.awssdk.services.inspector2.model.BatchGetAccountStatusResponse; +import software.amazon.awssdk.services.inspector2.model.ResourceState; +import software.amazon.awssdk.services.inspector2.model.Severity; +import software.amazon.awssdk.services.inspector2.model.StringComparison; +import software.amazon.awssdk.services.inspector2.model.StringFilter; +import software.amazon.awssdk.services.inspector2.model.Usage; +import software.amazon.awssdk.services.inspector2.model.UsageTotal; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class InspectorScenario { + + + 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("===================================="); + System.out.println(); + + // Step 1: Check current account status + System.out.println("Step 1: Checking Inspector account status..."); + var accountStatus = inspectorActions.getAccountStatus(inspectorClient); + displayAccountStatus(accountStatus); + + + // Step 2: Enable Inspector for resource types (if not already enabled) + System.out.println("Step 2: Ensuring Inspector is enabled..."); + List resourceTypes = List.of( + ResourceScanType.EC2, + ResourceScanType.ECR, + ResourceScanType.LAMBDA, + ResourceScanType.LAMBDA_CODE + ); + + + try { + inspectorActions.enableInspector(inspectorClient, resourceTypes, null); + } catch (Exception e) { + System.out.println("â„šī¸ Inspector may already be enabled: " + e.getMessage()); + } + + + // Step 3: List and analyze findings + System.out.println("Step 3: Analyzing security findings..."); + int maxResults = 10; + var findings = inspectorActions.listFindings(inspectorClient, maxResults, null); + displayFindings(findings); + System.out.println(); + + + // Step 4: Show coverage information + System.out.println("Step 4: Checking scan coverage..."); + maxResults = 5; + var coverage = inspectorActions.listCoverage(inspectorClient, maxResults); + displayCoverage(coverage); + System.out.println(); + + // Step 5: Create a findings filter (example) + System.out.println("Step 5: Creating a findings filter..."); + createExampleFilter(inspectorActions, inspectorClient); + System.out.println(); + + // Step 6: List existing filters + System.out.println("Step 6: Listing existing filters..."); + var filters = inspectorActions.listFilters(inspectorClient, 10); + displayFilters(filters); + System.out.println(); + + // Step 7: Show usage totals + System.out.println("Step 7: Checking usage and costs..."); + var usage = inspectorActions.listUsageTotals(inspectorClient, null, 10); + displayUsage(usage); + System.out.println(); + + // Step 8: Coverage statistics + System.out.println("Step 8: Getting coverage statistics..."); + var coverageStats = inspectorActions.listCoverageStatistics(inspectorClient); + displayCoverageStatistics(coverageStats); + 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"); + + + System.out.println();(); + System.out.println(" This concludes the AWS Inspector Service scenario."); + } + + /** + * Displays coverage statistics in a formatted way. + */ + private static void displayCoverageStatistics(ListCoverageStatisticsResponse statsResponse) { + List counts = statsResponse.countsByGroup(); + + if (counts == null || counts.isEmpty()) { + System.out.println("📊 No coverage statistics available"); + } else { + System.out.println("✅ Coverage Statistics:"); + for (Counts count : counts) { + System.out.println(" Group: " + count.groupKey()); + System.out.println(" Total Count: " + count.count()); + System.out.println(); + } + } + } + + + public static void displayUsage(ListUsageTotalsResponse usageResponse) { + List totals = usageResponse.totals(); + + if (totals == null || totals.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 : totals) { + System.out.println(" Account: " + total.accountId()); + List usageList = total.usage(); + if (usageList != null) { + 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(); + } + } + } + + public static void displayFilters(ListFiltersResponse filtersResponse) { + List filters = filtersResponse.filters(); + + if (filters == null || filters.isEmpty()) { + System.out.println("📭 No filters found"); + } else { + System.out.println("✅ Found " + filters.size() + " filter(s):"); + for (Filter filter : filters) { + 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(); + } + } + } + + + public static void createExampleFilter(InspectorActions inspectorActions, Inspector2Client inspectorClient) { + try { + CreateFilterResponse filterRes = inspectorActions.createFilter( + inspectorClient, + "Suppress low severity findings for demo purposes" + ); + + System.out.println("✅ Created example filter: " + filterRes.arn()); + + } catch (Exception e) { + System.out.println("â„šī¸ Could not create example filter: " + e.getMessage()); + } + } + public static void displayCoverage(ListCoverageResponse coverageResponse) { + List coveredResources = coverageResponse.coveredResources(); + + if (coveredResources == null || coveredResources.isEmpty()) { + System.out.println("📊 No coverage information available"); + } else { + System.out.println("✅ Coverage Information:"); + System.out.println(" Total resources covered: " + coveredResources.size()); + + // Group by resource type + Map> resourcesByType = coveredResources.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:"); + + // Show top 3 resources + for (int i = 0; i < Math.min(coveredResources.size(), 3); i++) { + CoveredResource resource = coveredResources.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()); + } + } + } + } + + + public static void displayAccountStatus(BatchGetAccountStatusResponse accountStatus) { + System.out.println("✅ Inspector Account Status:"); + + if (accountStatus.accounts() != null) { + for (AccountState account : accountStatus.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()); + } + } + } + } + + + public static void displayFindings(ListFindingsResponse findingsResponse) { + 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):"); + + // Group findings by severity + 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:"); + + // Show top 5 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(); + } + } + } +} From 7fc6ba12b9e31a8d5b62adcb53efacaec8c3c2d6 Mon Sep 17 00:00:00 2001 From: Macdonald Date: Mon, 27 Oct 2025 11:44:25 -0400 Subject: [PATCH 02/11] Add inspector spec --- scenarios/basics/inspector/SPECIFICATION.md | 141 ++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 scenarios/basics/inspector/SPECIFICATION.md diff --git a/scenarios/basics/inspector/SPECIFICATION.md b/scenarios/basics/inspector/SPECIFICATION.md new file mode 100644 index 00000000000..02c8146c4d0 --- /dev/null +++ b/scenarios/basics/inspector/SPECIFICATION.md @@ -0,0 +1,141 @@ +# Amazon Inspector Specification + +This document contains the specification for the *Amazon Inspector Basics Scenario*, based on the implemented Java code examples in `javav2/example_code/Inspector/`. The specification describes the actual code example scenario that demonstrates Amazon Inspector V2 vulnerability management capabilities using the AWS SDK for Java V2. + +### Relevant documentation + +* [Getting started with Amazon Inspector](https://docs.aws.amazon.com/inspector/latest/user/getting_started.html) +* [What is Amazon Inspector?](https://docs.aws.amazon.com/inspector/latest/user/what-is-inspector.html) +* [Amazon Inspector API Reference](https://docs.aws.amazon.com/inspector/v2/APIReference/Welcome.html) +* [Amazon Inspector Pricing](https://aws.amazon.com/inspector/pricing/) + +### API Actions Used + +**Core Operations (Implemented in InspectorActions.java):** +* [Enable](https://docs.aws.amazon.com/inspector/v2/APIReference/API_Enable.html) - Enable Inspector scanning for resource types +* [BatchGetAccountStatus](https://docs.aws.amazon.com/inspector/v2/APIReference/API_BatchGetAccountStatus.html) - Check account status and configuration +* [ListFindings](https://docs.aws.amazon.com/inspector/v2/APIReference/API_ListFindings.html) - List security findings with filtering +* [ListCoverage](https://docs.aws.amazon.com/inspector/v2/APIReference/API_ListCoverage.html) - Monitor resource scan coverage +* [ListCoverageStatistics](https://docs.aws.amazon.com/inspector/v2/APIReference/API_ListCoverageStatistics.html) - Get coverage statistics +* [ListUsageTotals](https://docs.aws.amazon.com/inspector/v2/APIReference/API_ListUsageTotals.html) - Track usage and costs +* [CreateFilter](https://docs.aws.amazon.com/inspector/v2/APIReference/API_CreateFilter.html) - Create filters to suppress findings +* [ListFilters](https://docs.aws.amazon.com/inspector/v2/APIReference/API_ListFilters.html) - List existing filters + +**Additional Operations (Available but not used in main scenario):** +* [BatchGetFindingDetails](https://docs.aws.amazon.com/inspector/v2/APIReference/API_BatchGetFindingDetails.html) - Get detailed finding information +* [Disable](https://docs.aws.amazon.com/inspector/v2/APIReference/API_Disable.html) - Disable Inspector scanning + +## Implemented Example Structure + +The implementation includes three main Java classes that demonstrate Amazon Inspector V2 capabilities: + +### HelloInspector.java + +**Purpose**: Basic connectivity verification and service introduction +**Location**: `javav2/example_code/Inspector/src/main/java/com/java/inspector/HelloInspector.java` + +**Operations Demonstrated**: +- Set up the Inspector2Client with proper region configuration +- Check current account status using BatchGetAccountStatus +- List recent security findings with basic information +- Display usage totals and cost information +- Provide comprehensive error handling and troubleshooting guidance + +**Key Features**: +- Uses BatchGetAccountStatus (not deprecated GetAccountStatus) +- Displays resource states for EC2, ECR, Lambda, and Lambda Code scanning +- Shows findings with severity, type, status, and affected resources +- Includes usage and cost tracking for the last 30 days +- Comprehensive error handling with user-friendly troubleshooting tips + +### InspectorActions.java + +**Purpose**: Comprehensive service operations library +**Location**: `javav2/example_code/Inspector/src/main/java/com/java/inspector/InspectorActions.java` + +**Implemented Methods**: +- `enableInspector()` - Enable Inspector for specified resource types +- `getAccountStatus()` - Get account status using BatchGetAccountStatus +- `listFindings()` - List findings with optional filtering +- `listCoverage()` - Get resource coverage information +- `listCoverageStatistics()` - Get coverage statistics +- `listUsageTotals()` - Get usage and cost information +- `createFilter()` - Create filters to suppress low-severity findings +- `listFilters()` - List existing filters + +### InspectorScenario.java + +**Purpose**: Complete 8-step workflow demonstration +**Location**: `javav2/example_code/Inspector/src/main/java/com/java/inspector/InspectorScenario.java` + +**Scenario Steps**: +1. Check Inspector account status and configuration +2. Enable Inspector for EC2, ECR, Lambda, and Lambda Code +3. Analyze security findings with severity grouping +4. Monitor scan coverage across resources +5. Create example filter to suppress low-severity findings +6. List and display existing filters +7. Track usage and costs +8. Display coverage statistics + +## Scenario + +#### Setup + +* Enable Amazon Inspector for the account +* Verify Inspector is successfully activated +* Display account status and enabled scan types + +#### Coverage Assessment + +* List coverage statistics for EC2 instances, ECR repositories, and Lambda functions +* Display resource coverage details +* Show scanning status for different resource types + +#### Findings Management + +* List security findings across all resource types +* Filter findings by severity level (CRITICAL, HIGH, MEDIUM, LOW) +* Retrieve detailed information for specific findings + +#### Vulnerability Analysis + +* Display vulnerability details including CVE information +* Show affected resources and remediation guidance +* Filter findings by resource type (EC2, ECR, Lambda) + +#### Cleanup + +* Optionally disable Inspector scanning (with user confirmation) +* Display final account status + +## Errors + +SDK Code examples include basic exception handling for each action used. The table below describes an appropriate exception which will be handled in the code for each service action. + +|Action |Error |Handling | +|--- |--- |--- | +|`Enable` |ValidationException |Validate resource types and account permissions. | +|`Enable` |AccessDeniedException |Notify user of insufficient permissions and exit. | +|`BatchGetAccountStatus` |ValidationException |Validate account IDs format. | +|`BatchGetAccountStatus` |AccessDeniedException |Handle permission errors gracefully. | +|`ListFindings` |ValidationException |Validate filter criteria and pagination parameters. | +|`ListFindings` |InternalServerException |Retry operation with exponential backoff. | +|`BatchGetFindingDetails` |ValidationException |Validate finding ARNs format. | +|`BatchGetFindingDetails` |AccessDeniedException |Handle access denied for specific findings. | +|`ListCoverage` |ValidationException |Validate filter and pagination parameters. | +|`Disable` |ValidationException |Validate resource types for disabling. | +|`Disable` |ConflictException |Handle cases where Inspector cannot be disabled. | + +## Metadata + +|action / scenario |metadata file |metadata key | +|--- |--- |--- | +|`Enable` |inspector_metadata.yaml |inspector_Enable | +|`BatchGetAccountStatus` |inspector_metadata.yaml |inspector_BatchGetAccountStatus | +|`ListFindings` |inspector_metadata.yaml |inspector_ListFindings | +|`BatchGetFindingDetails` |inspector_metadata.yaml |inspector_BatchGetFindingDetails | +|`ListCoverage` |inspector_metadata.yaml |inspector_ListCoverage | +|`Disable` |inspector_metadata.yaml |inspector_Disable | +|`Amazon Inspector Basics Scenario` |inspector_metadata.yaml |inspector_Scenario | + From 8b0e157e8e5ca32074e3ef7067702fa074ecc00a Mon Sep 17 00:00:00 2001 From: Macdonald Date: Mon, 27 Oct 2025 11:55:23 -0400 Subject: [PATCH 03/11] Add YAML file --- .doc_gen/metadata/inspector_metadata.yaml | 148 ++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 .doc_gen/metadata/inspector_metadata.yaml diff --git a/.doc_gen/metadata/inspector_metadata.yaml b/.doc_gen/metadata/inspector_metadata.yaml new file mode 100644 index 00000000000..32f2467c0ae --- /dev/null +++ b/.doc_gen/metadata/inspector_metadata.yaml @@ -0,0 +1,148 @@ +# zexi 0.4.2 +inspector_Hello: + title: Hello &Inspector; + title_abbrev: Hello &Inspector; + synopsis: get started using &Inspector;. + category: Hello + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.kotlin.hello.main + services: + inspector2: {BatchGetAccountStatus, ListFindings, ListUsageTotals} +inspector_EnableInspector: + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.kotlin.enable.main + services: + inspector2: {Enable} +inspector_DisableInspector: + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.kotlin.disable.main + services: + inspector2: {Disable} +inspector_GetAccountStatus: + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.kotlin.get_account_status.main + services: + inspector2: {BatchGetAccountStatus} +inspector_ListFindings: + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.kotlin.list_findings.main + services: + inspector2: {ListFindings} +inspector_BatchGetFindingDetails: + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.kotlin.batch_get_finding_details.main + services: + inspector2: {BatchGetFindingDetails} +inspector_ListCoverageStatistics: + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.kotlin.list_coverage_statistics.main + services: + inspector2: {ListCoverageStatistics} +inspector_ListCoverage: + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.kotlin.list_coverage.main + services: + inspector2: {ListCoverage} +inspector_ListUsageTotals: + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.kotlin.list_usage_totals.main + services: + inspector2: {ListUsageTotals} +inspector_DescribeOrganizationConfiguration: + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.kotlin.describe_organization_configuration.main + services: + inspector2: {DescribeOrganizationConfiguration} +inspector_UpdateOrganizationConfiguration: + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.kotlin.update_organization_configuration.main + services: + inspector2: {UpdateOrganizationConfiguration} \ No newline at end of file From 0ef440bc270fd4ea55dd85bb3f58ffc661e7070d Mon Sep 17 00:00:00 2001 From: Macdonald Date: Mon, 27 Oct 2025 15:56:16 -0400 Subject: [PATCH 04/11] updated YAML file --- .doc_gen/metadata/inspector_metadata.yaml | 144 ++++-- .../com/java/inspector/HelloInspector.java | 6 +- .../com/java/inspector/InspectorActions.java | 410 ++++++++++++++---- .../com/java/inspector/InspectorScenario.java | 294 ++++--------- .../iotsitewise/scenario/SitewiseActions.java | 1 - 5 files changed, 502 insertions(+), 353 deletions(-) diff --git a/.doc_gen/metadata/inspector_metadata.yaml b/.doc_gen/metadata/inspector_metadata.yaml index 32f2467c0ae..2d2f2866be3 100644 --- a/.doc_gen/metadata/inspector_metadata.yaml +++ b/.doc_gen/metadata/inspector_metadata.yaml @@ -5,144 +5,196 @@ inspector_Hello: synopsis: get started using &Inspector;. category: Hello languages: - Kotlin: + Java: versions: - - sdk_version: 1 - github: kotlin/services/inspector + - sdk_version: 2 + github: javav2/example_code/inspector sdkguide: excerpts: - description: snippet_tags: - - inspector.kotlin.hello.main + - inspector.java.hello.main services: - inspector2: {BatchGetAccountStatus, ListFindings, ListUsageTotals} + inspector: {BatchGetAccountStatus, ListFindings, ListUsageTotals} inspector_EnableInspector: languages: - Kotlin: + Java: versions: - - sdk_version: 1 - github: kotlin/services/inspector + - sdk_version: 2 + github: javav2/example_code/inspector sdkguide: excerpts: - description: snippet_tags: - - inspector.kotlin.enable.main + - inspector.java.enable.main services: inspector2: {Enable} +inspector_CreateFilter: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.java.create.filter.main + services: + inspector2: {CreateFilter} inspector_DisableInspector: languages: - Kotlin: + Java: versions: - - sdk_version: 1 - github: kotlin/services/inspector + - sdk_version: 2 + github: javav2/example_code/inspector sdkguide: excerpts: - description: snippet_tags: - - inspector.kotlin.disable.main + - inspector.java.disable.main services: inspector2: {Disable} inspector_GetAccountStatus: languages: - Kotlin: + Java: versions: - - sdk_version: 1 - github: kotlin/services/inspector + - sdk_version: 2 + github: javav2/example_code/inspector sdkguide: excerpts: - description: snippet_tags: - - inspector.kotlin.get_account_status.main + - inspector.java.get_account_status.main services: inspector2: {BatchGetAccountStatus} inspector_ListFindings: languages: - Kotlin: + Java: versions: - - sdk_version: 1 - github: kotlin/services/inspector + - sdk_version: 2 + github: javav2/example_code/inspector sdkguide: excerpts: - description: snippet_tags: - - inspector.kotlin.list_findings.main + - inspector.java.list_findings.main services: inspector2: {ListFindings} inspector_BatchGetFindingDetails: languages: - Kotlin: + Java: versions: - - sdk_version: 1 - github: kotlin/services/inspector + - sdk_version: 2 + github: javav2/example_code/inspector sdkguide: excerpts: - description: snippet_tags: - - inspector.kotlin.batch_get_finding_details.main + - inspector.java.batch_get_finding_details.main services: inspector2: {BatchGetFindingDetails} inspector_ListCoverageStatistics: languages: - Kotlin: + Java: versions: - - sdk_version: 1 - github: kotlin/services/inspector + - sdk_version: 2 + github: javav2/example_code/inspector sdkguide: excerpts: - description: snippet_tags: - - inspector.kotlin.list_coverage_statistics.main + - inspector.java.list_coverage_statistics.main services: inspector2: {ListCoverageStatistics} inspector_ListCoverage: languages: - Kotlin: + Java: versions: - - sdk_version: 1 - github: kotlin/services/inspector + - sdk_version: 2 + github: javav2/example_code/inspector sdkguide: excerpts: - description: snippet_tags: - - inspector.kotlin.list_coverage.main + - inspector.java.list_coverage.main services: inspector2: {ListCoverage} inspector_ListUsageTotals: languages: - Kotlin: + Java: versions: - - sdk_version: 1 - github: kotlin/services/inspector + - sdk_version: 2 + github: javav2/example_code/inspector sdkguide: excerpts: - description: snippet_tags: - - inspector.kotlin.list_usage_totals.main + - inspector.java.list_usage_totals.main services: inspector2: {ListUsageTotals} inspector_DescribeOrganizationConfiguration: languages: - Kotlin: + Java: versions: - - sdk_version: 1 - github: kotlin/services/inspector + - sdk_version: 2 + github: javav2/example_code/inspector sdkguide: excerpts: - description: snippet_tags: - - inspector.kotlin.describe_organization_configuration.main + - inspector.java.describe_organization_configuration.main services: inspector2: {DescribeOrganizationConfiguration} +inspector_ListFilters: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/inspector + sdkguide: + excerpts: + - description: + snippet_tags: + - inspector.java.list_filters.main + services: + inspector2: {inspector_ListFilters} inspector_UpdateOrganizationConfiguration: languages: - Kotlin: + Java: versions: - - sdk_version: 1 - github: kotlin/services/inspector + - sdk_version: 2 + github: javav2/example_code/inspector sdkguide: excerpts: - description: snippet_tags: - - inspector.kotlin.update_organization_configuration.main + - inspector.java.update_organization_configuration.main + services: + inspector2: {UpdateOrganizationConfiguration} +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: - inspector2: {UpdateOrganizationConfiguration} \ No newline at end of file + inspector: {} 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 index 634bd59c3a7..082d14d28a1 100644 --- 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 @@ -1,3 +1,6 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + package com.java.inspector; import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; @@ -18,6 +21,7 @@ import java.util.List; +// snippet-start:[inspector.java.hello.main] public class HelloInspector { public static void main(String[] args) { @@ -150,4 +154,4 @@ private static void showUsageTotals(Inspector2Client inspectorClient) { } } } - +// snippet-end:[inspector.java.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 index a951f8104d1..cca53fe1528 100644 --- 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 @@ -1,19 +1,36 @@ +// 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 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 { - // ---------------------- ENABLE INSPECTOR ---------------------- - public EnableResponse enableInspector( - Inspector2Client inspectorClient, - List resourceTypes, - List accountIds // can be null - ) { + // 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 + ); + + // Build request. EnableRequest.Builder requestBuilder = EnableRequest.builder() .resourceTypes(resourceTypes); @@ -22,37 +39,67 @@ public EnableResponse enableInspector( } EnableRequest request = requestBuilder.build(); - try { EnableResponse response = inspectorClient.enable(request); - System.out.println("✅ Inspector enable request completed"); - if (response.accounts() != null) { + 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); + System.out.println(" â€ĸ Account: " + accountId + " → Status: " + status); } + } else { + System.out.println(" Inspector may already be enabled for all target accounts."); } - return response; + } catch (ValidationException ve) { + System.out.println(" Inspector may already be enabled for this account: " + ve.getMessage()); - } catch (Exception e) { - System.err.println("❌ Failed to enable Inspector: " + e.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); } } - - // ---------------------- COVERAGE STATISTICS ---------------------- - public static ListCoverageStatisticsResponse listCoverageStatistics(Inspector2Client inspectorClient) { + // snippet-end:[inspector.java2_enable.main] + + // snippet-start:[inspector.java2.list_coverage.main] + /** + * Retrieves and prints the coverage statistics using the provided Inspector2Client. + * + * @param inspectorClient the Inspector2Client used to retrieve the coverage statistics + */ + public void listCoverageStatistics(Inspector2Client inspectorClient) { ListCoverageStatisticsRequest request = ListCoverageStatisticsRequest.builder() .build(); - return inspectorClient.listCoverageStatistics(request); + var statsResponse = inspectorClient.listCoverageStatistics(request); + List counts = statsResponse.countsByGroup(); + + if (counts == null || counts.isEmpty()) { + System.out.println("No coverage statistics available"); + } else { + System.out.println("Coverage Statistics:"); + for (Counts count : counts) { + System.out.println(" Group: " + count.groupKey()); + System.out.println(" Total Count: " + count.count()); + System.out.println(); + } + } } - - // ---------------------- LIST USAGE TOTALS ---------------------- - public ListUsageTotalsResponse listUsageTotals( + // snippet-end:[inspector.java2.list_coverage.main] + + // snippet-start:[inspector.java2.list_usage_totals.main] + /** + * Retrieves and prints the usage totals for the specified accounts using the provided Inspector2Client. + * + * @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 @@ -65,11 +112,40 @@ public ListUsageTotalsResponse listUsageTotals( } ListUsageTotalsRequest request = requestBuilder.build(); - return inspectorClient.listUsageTotals(request); + var usageResponse = inspectorClient.listUsageTotals(request); + + List totals = usageResponse.totals(); + + if (totals == null || totals.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 : totals) { + System.out.println(" Account: " + total.accountId()); + List usageList = total.usage(); + if (usageList != null) { + 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(); + } + } } - - // ---------------------- ACCOUNT STATUS ---------------------- - public BatchGetAccountStatusResponse getAccountStatus(Inspector2Client inspectorClient) { + // 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(); @@ -85,79 +161,138 @@ public BatchGetAccountStatusResponse getAccountStatus(Inspector2Client inspector } } - return response; - } + 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")); - // ---------------------- LIST FILTERS ---------------------- - public static ListFiltersResponse listFilters( - Inspector2Client inspector2Client, - Integer maxResults - ) { + // 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.java.list_filters.main] + /** + * Retrieves a list of filters configured in AWS Inspector2. + * + * @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"); + System.out.println("Listing filters..."); + // Build the request ListFiltersRequest.Builder requestBuilder = ListFiltersRequest.builder(); if (maxResults != null) { requestBuilder.maxResults(maxResults); } + // Execute the request ListFiltersResponse response = inspector2Client.listFilters(requestBuilder.build()); - - int count = response.filters() != null ? response.filters().size() : 0; - System.out.println("Successfully listed filters: " + count); - return response; + List filters = response.filters(); + + // Display results. + if (filters == null || filters.isEmpty()) { + System.out.println(" No filters found."); + } else { + System.out.println(" Found " + filters.size() + " filter(s):"); + for (Filter filter : filters) { + 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(); + } + } } catch (Inspector2Exception e) { - System.out.println("Failed to list filters: " + e.getMessage()); + System.err.println("Failed to list filters: " + e.awsErrorDetails().errorMessage()); + throw e; + } catch (Exception e) { + System.err.println("Unexpected error: " + e.getMessage()); throw e; } } - - // ---------------------- CREATE FILTER ---------------------- - public static CreateFilterResponse createFilter( - Inspector2Client inspector2Client, - String description - ) { - try { + // snippet-end:[inspector.java.list_filters.main] + + // snippet-start:[inspector.java.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); - // Build severity filter - StringFilter severityFilter = StringFilter.builder() - .value(Severity.LOW.toString()) - .comparison(StringComparison.EQUALS) - .build(); - - FilterCriteria filterCriteria = FilterCriteria.builder() - .severity(List.of(severityFilter)) - .build(); - - CreateFilterRequest createRequest = CreateFilterRequest.builder() - .name(filterName) - .filterCriteria(filterCriteria) - .action(FilterAction.SUPPRESS) - .description(description) - .build(); - - CreateFilterResponse response = inspector2Client.createFilter(createRequest); - System.out.println("✅ Successfully created filter with ARN: " + response.arn()); - return response; - - } 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; + 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; + } } - } - - // ---------------------- LIST FINDINGS ---------------------- - public ListFindingsResponse listFindings( - Inspector2Client inspectorClient, - int maxResults, - FilterCriteria filterCriteria // can be null + // snippet-end:[inspector.java.create.filter.main] + + // snippet-start:[inspector.java.list_findings.main] + /** + * Lists findings from AWS Inspector2, optionally filtered by criteria. + * + * @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); @@ -166,21 +301,122 @@ public ListFindingsResponse listFindings( } ListFindingsRequest request = requestBuilder.build(); - ListFindingsResponse response = inspectorClient.listFindings(request); + 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)"); + } - List findings = response.findings(); - int count = findings != null ? findings.size() : 0; - System.out.println("✅ Listed " + count + " findings"); + 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()); - return response; + } 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.java.list_findings.main] + + // snippet-start:[inspector.java.list_coverage.main] + /** + * Lists AWS Inspector2 coverage details for scanned resources. + * + * @param inspectorClient The Inspector2 client. + * @param maxResults Maximum number of resources to return. + */ + public void listCoverage(Inspector2Client inspectorClient, int maxResults) { - // ---------------------- LIST COVERAGE ---------------------- - public ListCoverageResponse listCoverage(Inspector2Client inspectorClient, int maxResults) { ListCoverageRequest request = ListCoverageRequest.builder() .maxResults(maxResults) .build(); - return inspectorClient.listCoverage(request); + try { + ListCoverageResponse response = inspectorClient.listCoverage(request); + List coveredResources = response.coveredResources(); + + if (coveredResources == null || coveredResources.isEmpty()) { + System.out.println(" No coverage information available."); + } else { + System.out.println(" Coverage Information:"); + System.out.println(" Total resources covered: " + coveredResources.size()); + + // Group resources by type + Map> resourcesByType = coveredResources.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:"); + + // Show top 3 sample resources + for (int i = 0; i < Math.min(coveredResources.size(), 3); i++) { + CoveredResource resource = coveredResources.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.java.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 index 529560f466f..aa4ffca4dc3 100644 --- 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 @@ -1,16 +1,18 @@ -package com.java.inspector; +// 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.Account; import software.amazon.awssdk.services.inspector2.model.AccountState; import software.amazon.awssdk.services.inspector2.model.BatchGetAccountStatusResponse; import software.amazon.awssdk.services.inspector2.model.Counts; import software.amazon.awssdk.services.inspector2.model.CoveredResource; import software.amazon.awssdk.services.inspector2.model.CreateFilterResponse; +import software.amazon.awssdk.services.inspector2.model.EnableResponse; import software.amazon.awssdk.services.inspector2.model.Filter; -import software.amazon.awssdk.services.inspector2.model.FilterAction; -import software.amazon.awssdk.services.inspector2.model.FilterCriteria; import software.amazon.awssdk.services.inspector2.model.Finding; import software.amazon.awssdk.services.inspector2.model.ListCoverageResponse; import software.amazon.awssdk.services.inspector2.model.ListCoverageStatisticsResponse; @@ -18,27 +20,18 @@ import software.amazon.awssdk.services.inspector2.model.ListFindingsResponse; import software.amazon.awssdk.services.inspector2.model.ListUsageTotalsResponse; import software.amazon.awssdk.services.inspector2.model.Resource; -import software.amazon.awssdk.services.inspector2.model.ResourceScanType; -import software.amazon.awssdk.services.inspector2.model.ResourceState; -import software.amazon.awssdk.services.inspector2.Inspector2Client; -import software.amazon.awssdk.services.inspector2.model.AccountState; -import software.amazon.awssdk.services.inspector2.model.BatchGetAccountStatusResponse; import software.amazon.awssdk.services.inspector2.model.ResourceState; -import software.amazon.awssdk.services.inspector2.model.Severity; -import software.amazon.awssdk.services.inspector2.model.StringComparison; -import software.amazon.awssdk.services.inspector2.model.StringFilter; import software.amazon.awssdk.services.inspector2.model.Usage; import software.amazon.awssdk.services.inspector2.model.UsageTotal; - -import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; +import java.util.Scanner; +// snippet-start:[inspector.java2_scenario.main] 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(); @@ -47,70 +40,92 @@ public static void main(String[] args) { .region(Region.US_EAST_1) .build() ; - System.out.println("🔍 Amazon Inspector Basics Scenario"); - System.out.println("===================================="); + 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..."); - var accountStatus = inspectorActions.getAccountStatus(inspectorClient); - displayAccountStatus(accountStatus); - + inspectorActions.getAccountStatus(inspectorClient); + 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..."); - List resourceTypes = List.of( - ResourceScanType.EC2, - ResourceScanType.ECR, - ResourceScanType.LAMBDA, - ResourceScanType.LAMBDA_CODE - ); - - - try { - inspectorActions.enableInspector(inspectorClient, resourceTypes, null); - } catch (Exception e) { - System.out.println("â„šī¸ Inspector may already be enabled: " + e.getMessage()); - } - + inspectorActions.enableInspector(inspectorClient, null); + waitForInputToContinue(scanner); // Step 3: List and analyze findings + System.out.println(DASHES); System.out.println("Step 3: Analyzing security findings..."); int maxResults = 10; - var findings = inspectorActions.listFindings(inspectorClient, maxResults, null); - displayFindings(findings); + inspectorActions.listFindings(inspectorClient, maxResults, null); System.out.println(); - + waitForInputToContinue(scanner); // Step 4: Show coverage information + System.out.println(DASHES); System.out.println("Step 4: Checking scan coverage..."); maxResults = 5; - var coverage = inspectorActions.listCoverage(inspectorClient, maxResults); - displayCoverage(coverage); + inspectorActions.listCoverage(inspectorClient, maxResults); 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..."); - createExampleFilter(inspectorActions, inspectorClient); + try { + inspectorActions.createFilter( + inspectorClient, + "Suppress low severity findings for demo purposes" + ); + + System.out.println("Created example filter"); + + } catch (Exception e) { + System.out.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..."); - var filters = inspectorActions.listFilters(inspectorClient, 10); - displayFilters(filters); + inspectorActions.listFilters(inspectorClient, 10); System.out.println(); + waitForInputToContinue(scanner); // Step 7: Show usage totals + System.out.println(DASHES); System.out.println("Step 7: Checking usage and costs..."); - var usage = inspectorActions.listUsageTotals(inspectorClient, null, 10); - displayUsage(usage); + inspectorActions.listUsageTotals(inspectorClient, null, 10); System.out.println(); + waitForInputToContinue(scanner); // Step 8: Coverage statistics + System.out.println(DASHES); System.out.println("Step 8: Getting coverage statistics..."); - var coverageStats = inspectorActions.listCoverageStatistics(inspectorClient); - displayCoverageStatistics(coverageStats); + inspectorActions.listCoverageStatistics(inspectorClient); System.out.println(); System.out.println("🎉 Inspector Basics scenario completed successfully!"); @@ -128,184 +143,27 @@ public static void main(String[] args) { 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(); System.out.println(" This concludes the AWS Inspector Service scenario."); } - /** - * Displays coverage statistics in a formatted way. - */ - private static void displayCoverageStatistics(ListCoverageStatisticsResponse statsResponse) { - List counts = statsResponse.countsByGroup(); - - if (counts == null || counts.isEmpty()) { - System.out.println("📊 No coverage statistics available"); - } else { - System.out.println("✅ Coverage Statistics:"); - for (Counts count : counts) { - System.out.println(" Group: " + count.groupKey()); - System.out.println(" Total Count: " + count.count()); - System.out.println(); - } - } - } - - - public static void displayUsage(ListUsageTotalsResponse usageResponse) { - List totals = usageResponse.totals(); - - if (totals == null || totals.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 : totals) { - System.out.println(" Account: " + total.accountId()); - List usageList = total.usage(); - if (usageList != null) { - 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(); - } - } - } - - public static void displayFilters(ListFiltersResponse filtersResponse) { - List filters = filtersResponse.filters(); - - if (filters == null || filters.isEmpty()) { - System.out.println("📭 No filters found"); - } else { - System.out.println("✅ Found " + filters.size() + " filter(s):"); - for (Filter filter : filters) { - 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(); - } - } - } - - - public static void createExampleFilter(InspectorActions inspectorActions, Inspector2Client inspectorClient) { - try { - CreateFilterResponse filterRes = inspectorActions.createFilter( - inspectorClient, - "Suppress low severity findings for demo purposes" - ); - - System.out.println("✅ Created example filter: " + filterRes.arn()); - - } catch (Exception e) { - System.out.println("â„šī¸ Could not create example filter: " + e.getMessage()); - } - } - public static void displayCoverage(ListCoverageResponse coverageResponse) { - List coveredResources = coverageResponse.coveredResources(); - - if (coveredResources == null || coveredResources.isEmpty()) { - System.out.println("📊 No coverage information available"); - } else { - System.out.println("✅ Coverage Information:"); - System.out.println(" Total resources covered: " + coveredResources.size()); - - // Group by resource type - Map> resourcesByType = coveredResources.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:"); - - // Show top 3 resources - for (int i = 0; i < Math.min(coveredResources.size(), 3); i++) { - CoveredResource resource = coveredResources.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()); - } - } - } - } - - - public static void displayAccountStatus(BatchGetAccountStatusResponse accountStatus) { - System.out.println("✅ Inspector Account Status:"); - - if (accountStatus.accounts() != null) { - for (AccountState account : accountStatus.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()); - } - } - } - } - - - public static void displayFindings(ListFindingsResponse findingsResponse) { - 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):"); - - // Group findings by severity - 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:"); - - // Show top 5 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()); - } + 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 (finding.inspectorScore() != null) { - System.out.println(" Inspector Score: " + finding.inspectorScore()); - } - System.out.println(); + 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/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 079ca3a48da..8dcd208152a 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; From 62a41d015c72875c7773648448a7ca3f002bc994 Mon Sep 17 00:00:00 2001 From: Macdonald Date: Mon, 27 Oct 2025 16:23:22 -0400 Subject: [PATCH 05/11] updated YAML file --- .doc_gen/metadata/inspector_metadata.yaml | 77 +++++-------------- .../com/java/inspector/HelloInspector.java | 4 +- .../com/java/inspector/InspectorActions.java | 20 ++--- 3 files changed, 31 insertions(+), 70 deletions(-) diff --git a/.doc_gen/metadata/inspector_metadata.yaml b/.doc_gen/metadata/inspector_metadata.yaml index 2d2f2866be3..680776af22b 100644 --- a/.doc_gen/metadata/inspector_metadata.yaml +++ b/.doc_gen/metadata/inspector_metadata.yaml @@ -13,7 +13,7 @@ inspector_Hello: excerpts: - description: snippet_tags: - - inspector.java.hello.main + - inspector.java2.hello.main services: inspector: {BatchGetAccountStatus, ListFindings, ListUsageTotals} inspector_EnableInspector: @@ -26,9 +26,9 @@ inspector_EnableInspector: excerpts: - description: snippet_tags: - - inspector.java.enable.main + - inspector.java2.enable.main services: - inspector2: {Enable} + inspector: {Enable} inspector_CreateFilter: languages: Java: @@ -39,22 +39,9 @@ inspector_CreateFilter: excerpts: - description: snippet_tags: - - inspector.java.create.filter.main + - inspector.java2.create.filter.main services: - inspector2: {CreateFilter} -inspector_DisableInspector: - languages: - Java: - versions: - - sdk_version: 2 - github: javav2/example_code/inspector - sdkguide: - excerpts: - - description: - snippet_tags: - - inspector.java.disable.main - services: - inspector2: {Disable} + inspector: {CreateFilter} inspector_GetAccountStatus: languages: Java: @@ -65,9 +52,9 @@ inspector_GetAccountStatus: excerpts: - description: snippet_tags: - - inspector.java.get_account_status.main + - inspector.java2.get_account_status.main services: - inspector2: {BatchGetAccountStatus} + inspector: {BatchGetAccountStatus} inspector_ListFindings: languages: Java: @@ -78,9 +65,9 @@ inspector_ListFindings: excerpts: - description: snippet_tags: - - inspector.java.list_findings.main + - inspector.java2.list_findings.main services: - inspector2: {ListFindings} + inspector: {ListFindings} inspector_BatchGetFindingDetails: languages: Java: @@ -91,9 +78,9 @@ inspector_BatchGetFindingDetails: excerpts: - description: snippet_tags: - - inspector.java.batch_get_finding_details.main + - inspector.java2.get_account_status.main services: - inspector2: {BatchGetFindingDetails} + inspector: {BatchGetFindingDetails} inspector_ListCoverageStatistics: languages: Java: @@ -104,9 +91,9 @@ inspector_ListCoverageStatistics: excerpts: - description: snippet_tags: - - inspector.java.list_coverage_statistics.main + - inspector.java2.list_coverage.main services: - inspector2: {ListCoverageStatistics} + inspector: {ListCoverageStatistics} inspector_ListCoverage: languages: Java: @@ -117,9 +104,9 @@ inspector_ListCoverage: excerpts: - description: snippet_tags: - - inspector.java.list_coverage.main + - inspector.java2.list_coverage.main services: - inspector2: {ListCoverage} + inspector: {ListCoverage} inspector_ListUsageTotals: languages: Java: @@ -130,22 +117,9 @@ inspector_ListUsageTotals: excerpts: - description: snippet_tags: - - inspector.java.list_usage_totals.main - services: - inspector2: {ListUsageTotals} -inspector_DescribeOrganizationConfiguration: - languages: - Java: - versions: - - sdk_version: 2 - github: javav2/example_code/inspector - sdkguide: - excerpts: - - description: - snippet_tags: - - inspector.java.describe_organization_configuration.main + - inspector.java2.list_usage_totals.main services: - inspector2: {DescribeOrganizationConfiguration} + inspector: {ListUsageTotals} inspector_ListFilters: languages: Java: @@ -156,22 +130,9 @@ inspector_ListFilters: excerpts: - description: snippet_tags: - - inspector.java.list_filters.main - services: - inspector2: {inspector_ListFilters} -inspector_UpdateOrganizationConfiguration: - languages: - Java: - versions: - - sdk_version: 2 - github: javav2/example_code/inspector - sdkguide: - excerpts: - - description: - snippet_tags: - - inspector.java.update_organization_configuration.main + - inspector.java2.list_filters.main services: - inspector2: {UpdateOrganizationConfiguration} + inspector: {inspector_ListFilters} inspector_Scenario: synopsis_list: - Check Inspector account status. 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 index 082d14d28a1..b48524fd7b2 100644 --- 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 @@ -21,7 +21,7 @@ import java.util.List; -// snippet-start:[inspector.java.hello.main] +// snippet-start:[inspector.java2.hello.main] public class HelloInspector { public static void main(String[] args) { @@ -154,4 +154,4 @@ private static void showUsageTotals(Inspector2Client inspectorClient) { } } } -// snippet-end:[inspector.java.hello.main] +// 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 index cca53fe1528..8830d2559fc 100644 --- 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 @@ -13,7 +13,7 @@ // snippet-start:[inspector.java2_actions.main] public class InspectorActions { - // snippet-start:[inspector.java2_enable.main] + // snippet-start:[inspector.java2.enable.main] /** * Enables AWS Inspector for the provided account(s) and default resource types. * @@ -63,7 +63,7 @@ public void enableInspector(Inspector2Client inspectorClient, List accou throw new RuntimeException("Failed to enable Inspector: " + e.getMessage(), e); } } - // snippet-end:[inspector.java2_enable.main] + // snippet-end:[inspector.java2.enable.main] // snippet-start:[inspector.java2.list_coverage.main] /** @@ -181,7 +181,7 @@ public void getAccountStatus(Inspector2Client inspectorClient) { } // snippet-end:[inspector.java2.get_account_status.main] - // snippet-start:[inspector.java.list_filters.main] + // snippet-start:[inspector.java2.list_filters.main] /** * Retrieves a list of filters configured in AWS Inspector2. * @@ -227,9 +227,9 @@ public void listFilters(Inspector2Client inspector2Client, Integer maxResults) { throw e; } } - // snippet-end:[inspector.java.list_filters.main] + // snippet-end:[inspector.java2.list_filters.main] - // snippet-start:[inspector.java.create.filter.main] + // snippet-start:[inspector.java2.create.filter.main] /** * Creates a new filter in AWS Inspector2 to suppress findings of low severity. * @@ -277,9 +277,9 @@ public void createFilter(Inspector2Client inspector2Client, String description) throw e; } } - // snippet-end:[inspector.java.create.filter.main] + // snippet-end:[inspector.java2.create.filter.main] - // snippet-start:[inspector.java.list_findings.main] + // snippet-start:[inspector.java2.list_findings.main] /** * Lists findings from AWS Inspector2, optionally filtered by criteria. * @@ -352,9 +352,9 @@ public void listFindings( throw new RuntimeException("Failed to list findings: " + e.getMessage(), e); } } - // snippet-end:[inspector.java.list_findings.main] + // snippet-end:[inspector.java2.list_findings.main] - // snippet-start:[inspector.java.list_coverage.main] + // snippet-start:[inspector.java2.list_coverage.main] /** * Lists AWS Inspector2 coverage details for scanned resources. * @@ -417,6 +417,6 @@ public void listCoverage(Inspector2Client inspectorClient, int maxResults) { throw new RuntimeException("Failed to list coverage: " + e.getMessage(), e); } } - // snippet-end:[inspector.java.list_coverage.main] + // snippet-end:[inspector.java2.list_coverage.main] } // snippet-end:[inspector.java2_actions.main] \ No newline at end of file From da4bf715249a3ca1b47869282fe1c9c4f7870cfc Mon Sep 17 00:00:00 2001 From: Macdonald Date: Mon, 27 Oct 2025 16:32:29 -0400 Subject: [PATCH 06/11] updated YAML file --- .doc_gen/metadata/inspector_metadata.yaml | 2 +- .../src/main/java/com/java/inspector/HelloInspector.java | 2 -- .../src/main/java/com/java/inspector/InspectorActions.java | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.doc_gen/metadata/inspector_metadata.yaml b/.doc_gen/metadata/inspector_metadata.yaml index 680776af22b..094257f5d5f 100644 --- a/.doc_gen/metadata/inspector_metadata.yaml +++ b/.doc_gen/metadata/inspector_metadata.yaml @@ -91,7 +91,7 @@ inspector_ListCoverageStatistics: excerpts: - description: snippet_tags: - - inspector.java2.list_coverage.main + - inspector.java2.list_coverage.stats.main services: inspector: {ListCoverageStatistics} inspector_ListCoverage: 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 index b48524fd7b2..802e6ee26bf 100644 --- 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 @@ -26,8 +26,6 @@ public class HelloInspector { public static void main(String[] args) { System.out.println("🔍 Hello Amazon Inspector!"); - System.out.println("========================================\n"); - Region region = Region.US_EAST_1; try (Inspector2Client inspectorClient = Inspector2Client.builder() 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 index 8830d2559fc..ce105503dfd 100644 --- 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 @@ -65,7 +65,7 @@ public void enableInspector(Inspector2Client inspectorClient, List accou } // snippet-end:[inspector.java2.enable.main] - // snippet-start:[inspector.java2.list_coverage.main] + // snippet-start:[inspector.java2.list_coverage.stats.main] /** * Retrieves and prints the coverage statistics using the provided Inspector2Client. * @@ -89,7 +89,7 @@ public void listCoverageStatistics(Inspector2Client inspectorClient) { } } } - // snippet-end:[inspector.java2.list_coverage.main] + // snippet-end:[inspector.java2.list_coverage.stats.main] // snippet-start:[inspector.java2.list_usage_totals.main] /** From 3add2dfbca7a55ffc92550fdea3f45e8029b990d Mon Sep 17 00:00:00 2001 From: Macdonald Date: Tue, 28 Oct 2025 14:46:04 -0400 Subject: [PATCH 07/11] added tests --- .../com/java/inspector/HelloInspector.java | 108 ++++++-- .../com/java/inspector/InspectorActions.java | 259 +++++++++++------- .../com/java/inspector/InspectorScenario.java | 93 ++++--- .../src/test/java/InspectorTests.java | 64 +++++ 4 files changed, 367 insertions(+), 157 deletions(-) create mode 100644 javav2/example_code/inspector/src/test/java/InspectorTests.java 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 index 802e6ee26bf..d52e9864f11 100644 --- 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 @@ -3,7 +3,6 @@ package com.java.inspector; -import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.inspector2.Inspector2Client; import software.amazon.awssdk.services.inspector2.model.BatchGetAccountStatusRequest; @@ -18,37 +17,46 @@ 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!"); + 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..."); + System.out.println("Checking Inspector account status..."); checkAccountStatus(inspectorClient); System.out.println(); - System.out.println("📋 Checking for recent findings..."); + System.out.println("Checking for recent findings..."); listRecentFindings(inspectorClient); System.out.println(); - System.out.println("💰 Checking usage totals..."); + System.out.println("Checking usage totals..."); showUsageTotals(inspectorClient); System.out.println(); - System.out.println("🎉 Hello Inspector example completed successfully!"); + System.out.println("Hello Inspector example completed successfully!"); } catch (Inspector2Exception e) { - System.err.println("❌ Error: " + e.getMessage()); - System.err.println("🔧 Troubleshooting:"); + 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"); @@ -56,20 +64,25 @@ public static void main(String[] args) { } } - // ✅ Fixed version using BatchGetAccountStatus - private static void checkAccountStatus(Inspector2Client inspectorClient) { + /** + * 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."); + System.out.println(" No account information returned."); return; } for (AccountState account : accounts) { - System.out.println("✅ Account: " + account.accountId()); + System.out.println(" Account: " + account.accountId()); ResourceState resources = account.resourceState(); if (resources == null) { System.out.println(" No resource state data available."); @@ -85,11 +98,11 @@ private static void checkAccountStatus(Inspector2Client inspectorClient) { } } catch (Inspector2Exception e) { - System.err.println("❌ Failed to retrieve account status: " + e.awsErrorDetails().errorMessage()); + System.err.println(" Failed to retrieve account status: " + e.awsErrorDetails().errorMessage()); } } - private static void printState(String name, State state) { + public static void printState(String name, State state) { if (state == null) { System.out.println(" - " + name + ": (no data)"); return; @@ -98,7 +111,12 @@ private static void printState(String name, State state) { System.out.println(" - " + name + ": " + state.status() + err); } - private static void listRecentFindings(Inspector2Client inspectorClient) { + /** + * 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) @@ -108,9 +126,9 @@ private static void listRecentFindings(Inspector2Client inspectorClient) { List findings = response.findings(); if (findings == null || findings.isEmpty()) { - System.out.println("📭 No findings found."); + System.out.println(" No findings found."); } else { - System.out.println("✅ Found " + findings.size() + " recent finding(s):"); + 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()); @@ -121,34 +139,64 @@ private static void listRecentFindings(Inspector2Client inspectorClient) { } } catch (Inspector2Exception e) { - System.err.println("❌ Error listing findings: " + e.awsErrorDetails().errorMessage()); + System.err.println(" Error listing findings: " + e.awsErrorDetails().errorMessage()); } } - private static void showUsageTotals(Inspector2Client inspectorClient) { + /** + * 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(); - ListUsageTotalsResponse response = inspectorClient.listUsageTotals(request); - List totals = response.totals(); + // 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); + } + } - if (totals == null || totals.isEmpty()) { - System.out.println("📊 No usage data available yet."); + // 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 : totals) { + System.out.println(" Usage Totals (Last 30 days):"); + for (UsageTotal total : allTotals) { System.out.println(" Account: " + total.accountId()); - total.usage().forEach(u -> - System.out.println(" - " + u.type() + ": " + u.total() + - " (Est. Monthly: " + u.estimatedMonthlyCost() + " " + u.currency() + ")")); + 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()); + 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); } } } 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 index ce105503dfd..9aa1967fb30 100644 --- 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 @@ -5,6 +5,11 @@ 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; @@ -22,7 +27,7 @@ public class InspectorActions { */ public void enableInspector(Inspector2Client inspectorClient, List accountIds) { - // Default resource types to enable + // Default resource types to enable. List resourceTypes = List.of( ResourceScanType.EC2, ResourceScanType.ECR, @@ -30,7 +35,6 @@ public void enableInspector(Inspector2Client inspectorClient, List accou ResourceScanType.LAMBDA_CODE ); - // Build request. EnableRequest.Builder requestBuilder = EnableRequest.builder() .resourceTypes(resourceTypes); @@ -67,33 +71,57 @@ public void enableInspector(Inspector2Client inspectorClient, List accou // snippet-start:[inspector.java2.list_coverage.stats.main] /** - * Retrieves and prints the coverage statistics using the provided Inspector2Client. + * Retrieves and prints the coverage statistics using a paginator. * * @param inspectorClient the Inspector2Client used to retrieve the coverage statistics */ public void listCoverageStatistics(Inspector2Client inspectorClient) { - ListCoverageStatisticsRequest request = ListCoverageStatisticsRequest.builder() - .build(); - - var statsResponse = inspectorClient.listCoverageStatistics(request); - List counts = statsResponse.countsByGroup(); + 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); + } + } - if (counts == null || counts.isEmpty()) { - System.out.println("No coverage statistics available"); - } else { - System.out.println("Coverage Statistics:"); - for (Counts count : counts) { - System.out.println(" Group: " + count.groupKey()); - System.out.println(" Total Count: " + count.count()); - System.out.println(); + // 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 the provided Inspector2Client. + * 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. @@ -104,37 +132,61 @@ public void listUsageTotals( List accountIds, int maxResults ) { - ListUsageTotalsRequest.Builder requestBuilder = ListUsageTotalsRequest.builder() - .maxResults(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); - } + if (accountIds != null && !accountIds.isEmpty()) { + requestBuilder.accountIds(accountIds); + } + + ListUsageTotalsRequest request = requestBuilder.build(); + + // Create paginator. + ListUsageTotalsIterable paginator = inspectorClient.listUsageTotalsPaginator(request); - ListUsageTotalsRequest request = requestBuilder.build(); - var usageResponse = inspectorClient.listUsageTotals(request); - - List totals = usageResponse.totals(); - - if (totals == null || totals.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 : totals) { - System.out.println(" Account: " + total.accountId()); - List usageList = total.usage(); - if (usageList != null) { - 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()); + 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(); } - 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] @@ -151,7 +203,6 @@ public void getAccountStatus(Inspector2Client inspectorClient) { .build(); BatchGetAccountStatusResponse response = inspectorClient.batchGetAccountStatus(request); - if (response.accounts() != null) { for (AccountState account : response.accounts()) { String state = (account.state() != null && account.state().status() != null) @@ -183,7 +234,7 @@ public void getAccountStatus(Inspector2Client inspectorClient) { // snippet-start:[inspector.java2.list_filters.main] /** - * Retrieves a list of filters configured in AWS Inspector2. + * 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. @@ -192,24 +243,25 @@ public void getAccountStatus(Inspector2Client inspectorClient) { */ public void listFilters(Inspector2Client inspector2Client, Integer maxResults) { try { - System.out.println("Listing filters..."); - - // Build the request + System.out.println("Listing filters using paginator..."); ListFiltersRequest.Builder requestBuilder = ListFiltersRequest.builder(); if (maxResults != null) { requestBuilder.maxResults(maxResults); } - // Execute the request - ListFiltersResponse response = inspector2Client.listFilters(requestBuilder.build()); - List filters = response.filters(); + // 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; + } - // Display results. - if (filters == null || filters.isEmpty()) { - System.out.println(" No filters found."); - } else { - System.out.println(" Found " + filters.size() + " filter(s):"); for (Filter filter : filters) { + totalCount++; System.out.println(" - " + filter.name()); System.out.println(" ARN: " + filter.arn()); System.out.println(" Action: " + filter.action()); @@ -219,6 +271,12 @@ public void listFilters(Inspector2Client inspector2Client, Integer maxResults) { } } + 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; @@ -246,18 +304,18 @@ public void createFilter(Inspector2Client inspector2Client, String description) System.out.println("Creating filter: " + filterName); try { - // Define a filter to match LOW severity findings + // 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 + // Create filter criteria using the severity filter. FilterCriteria filterCriteria = FilterCriteria.builder() .severity(Collections.singletonList(severityFilter)) .build(); - // Build the filter creation request + // Build the filter creation request. CreateFilterRequest createRequest = CreateFilterRequest.builder() .name(filterName) .filterCriteria(filterCriteria) @@ -281,16 +339,16 @@ public void createFilter(Inspector2Client inspector2Client, String description) // snippet-start:[inspector.java2.list_findings.main] /** - * Lists findings from AWS Inspector2, optionally filtered by criteria. + * 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 + Inspector2Client inspectorClient, + int maxResults, + FilterCriteria filterCriteria ) { // Build the request ListFindingsRequest.Builder requestBuilder = ListFindingsRequest.builder() @@ -356,58 +414,69 @@ public void listFindings( // snippet-start:[inspector.java2.list_coverage.main] /** - * Lists AWS Inspector2 coverage details for scanned resources. + * 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) { - - ListCoverageRequest request = ListCoverageRequest.builder() - .maxResults(maxResults) - .build(); - try { - ListCoverageResponse response = inspectorClient.listCoverage(request); - List coveredResources = response.coveredResources(); + 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 (coveredResources == null || coveredResources.isEmpty()) { + if (allCoveredResources.isEmpty()) { System.out.println(" No coverage information available."); - } else { - System.out.println(" Coverage Information:"); - System.out.println(" Total resources covered: " + coveredResources.size()); + System.out.println(" This likely means Inspector hasn't yet scanned your resources or no supported resource types are present."); + return; + } - // Group resources by type - Map> resourcesByType = coveredResources.stream() - .collect(Collectors.groupingBy(CoveredResource::resourceTypeAsString)); + System.out.println(" Coverage Information:"); + System.out.println(" Total resources covered: " + allCoveredResources.size()); - for (Map.Entry> entry : resourcesByType.entrySet()) { - System.out.println(" " + entry.getKey() + ": " + entry.getValue().size() + " resource(s)"); - } + // Group by resource type. + Map> resourcesByType = allCoveredResources.stream() + .collect(Collectors.groupingBy(CoveredResource::resourceTypeAsString)); - System.out.println(); - System.out.println(" Sample covered resources:"); + for (Map.Entry> entry : resourcesByType.entrySet()) { + System.out.println(" " + entry.getKey() + ": " + entry.getValue().size() + " resource(s)"); + } - // Show top 3 sample resources - for (int i = 0; i < Math.min(coveredResources.size(), 3); i++) { - CoveredResource resource = coveredResources.get(i); - System.out.println(" - " + resource.resourceTypeAsString() + ": " + resource.resourceId()); - System.out.println(" Scan Type: " + resource.scanTypeAsString()); + System.out.println(); + System.out.println(" Sample covered resources:"); - if (resource.scanStatus() != null) { - System.out.println(" Status: " + resource.scanStatus().statusCodeAsString()); - } + // 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.accountId() != null) { - System.out.println(" Account ID: " + resource.accountId()); - } - System.out.println(); + 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."); + 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()); 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 index aa4ffca4dc3..c145cee420f 100644 --- 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 @@ -5,29 +5,17 @@ import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.inspector2.Inspector2Client; -import software.amazon.awssdk.services.inspector2.model.Account; -import software.amazon.awssdk.services.inspector2.model.AccountState; -import software.amazon.awssdk.services.inspector2.model.BatchGetAccountStatusResponse; -import software.amazon.awssdk.services.inspector2.model.Counts; -import software.amazon.awssdk.services.inspector2.model.CoveredResource; -import software.amazon.awssdk.services.inspector2.model.CreateFilterResponse; -import software.amazon.awssdk.services.inspector2.model.EnableResponse; -import software.amazon.awssdk.services.inspector2.model.Filter; -import software.amazon.awssdk.services.inspector2.model.Finding; -import software.amazon.awssdk.services.inspector2.model.ListCoverageResponse; -import software.amazon.awssdk.services.inspector2.model.ListCoverageStatisticsResponse; -import software.amazon.awssdk.services.inspector2.model.ListFiltersResponse; -import software.amazon.awssdk.services.inspector2.model.ListFindingsResponse; -import software.amazon.awssdk.services.inspector2.model.ListUsageTotalsResponse; -import software.amazon.awssdk.services.inspector2.model.Resource; -import software.amazon.awssdk.services.inspector2.model.ResourceState; -import software.amazon.awssdk.services.inspector2.model.Usage; -import software.amazon.awssdk.services.inspector2.model.UsageTotal; -import java.util.List; -import java.util.Map; 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", "-"); @@ -63,31 +51,55 @@ by Amazon Web Services (AWS) that helps improve the security waitForInputToContinue(scanner); - // Step 1: Check current account status + // Step 1: Check current account status. System.out.println(DASHES); System.out.println("Step 1: Checking Inspector account status..."); - inspectorActions.getAccountStatus(inspectorClient); + + 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) + // Step 2: Enable Inspector for resource types (if not already enabled). System.out.println(DASHES); System.out.println("Step 2: Ensuring Inspector is enabled..."); - inspectorActions.enableInspector(inspectorClient, null); + + 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 + // Step 3: List and analyze findings. System.out.println(DASHES); System.out.println("Step 3: Analyzing security findings..."); int maxResults = 10; - inspectorActions.listFindings(inspectorClient, maxResults, null); + + 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 + // Step 4: Show coverage information. System.out.println(DASHES); System.out.println("Step 4: Checking scan coverage..."); maxResults = 5; - inspectorActions.listCoverage(inspectorClient, maxResults); + + try { + inspectorActions.listCoverage(inspectorClient, maxResults); + + } catch (Exception e) { + System.err.println(" Could not create example filter: " + e.getMessage()); + } System.out.println(); waitForInputToContinue(scanner); @@ -103,7 +115,7 @@ by Amazon Web Services (AWS) that helps improve the security System.out.println("Created example filter"); } catch (Exception e) { - System.out.println(" Could not create example filter: " + e.getMessage()); + System.err.println(" Could not create example filter: " + e.getMessage()); } System.out.println(); waitForInputToContinue(scanner); @@ -111,21 +123,38 @@ by Amazon Web Services (AWS) that helps improve the security // Step 6: List existing filters System.out.println(DASHES); System.out.println("Step 6: Listing existing filters..."); - inspectorActions.listFilters(inspectorClient, 10); + + 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..."); - inspectorActions.listUsageTotals(inspectorClient, null, 10); + + 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..."); - inspectorActions.listCoverageStatistics(inspectorClient); + + 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!"); 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..df65d173064 --- /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"); + } +} From 299fdb40e47d1196ff0945493b4333b38a6507fb Mon Sep 17 00:00:00 2001 From: Macdonald Date: Tue, 4 Nov 2025 09:31:38 -0500 Subject: [PATCH 08/11] update spec --- javav2/example_code/inspector/src/test/java/InspectorTests.java | 2 +- scenarios/basics/inspector/SPECIFICATION.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/javav2/example_code/inspector/src/test/java/InspectorTests.java b/javav2/example_code/inspector/src/test/java/InspectorTests.java index df65d173064..b4f2620ecf8 100644 --- a/javav2/example_code/inspector/src/test/java/InspectorTests.java +++ b/javav2/example_code/inspector/src/test/java/InspectorTests.java @@ -38,7 +38,7 @@ public void testHelloService() { HelloInspector.listRecentFindings(inspector); HelloInspector.showUsageTotals(inspector); }); - System.out.println("Test 1 passed"); + System.out.println("Test 1 passed"); } @Test diff --git a/scenarios/basics/inspector/SPECIFICATION.md b/scenarios/basics/inspector/SPECIFICATION.md index 02c8146c4d0..8681d700272 100644 --- a/scenarios/basics/inspector/SPECIFICATION.md +++ b/scenarios/basics/inspector/SPECIFICATION.md @@ -1,6 +1,6 @@ # Amazon Inspector Specification -This document contains the specification for the *Amazon Inspector Basics Scenario*, based on the implemented Java code examples in `javav2/example_code/Inspector/`. The specification describes the actual code example scenario that demonstrates Amazon Inspector V2 vulnerability management capabilities using the AWS SDK for Java V2. +This document contains the specification for the *Amazon Inspector Basics Scenario*, based on the implemented Java code examples in `javav2/example_code/inspector/`. The specification describes the actual code example scenario that demonstrates Amazon Inspector V2 vulnerability management capabilities using the AWS SDK for Java V2. ### Relevant documentation From 4aecfb0dd44644b79b2e7d01f85526d11ba665b2 Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Mon, 24 Nov 2025 12:18:08 -0500 Subject: [PATCH 09/11] add inspector examples --- .../src/main/java/com/java/inspector/HelloInspector.java | 1 - 1 file changed, 1 deletion(-) 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 index d52e9864f11..bed9d6e69a4 100644 --- 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 @@ -35,7 +35,6 @@ 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()) { From 9f40d1b53b4ed1e94e59d116105e53487592fa72 Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Mon, 24 Nov 2025 13:31:54 -0500 Subject: [PATCH 10/11] add inspector examples --- scenarios/basics/inspector/SPECIFICATION.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scenarios/basics/inspector/SPECIFICATION.md b/scenarios/basics/inspector/SPECIFICATION.md index 8681d700272..ab170ff97f2 100644 --- a/scenarios/basics/inspector/SPECIFICATION.md +++ b/scenarios/basics/inspector/SPECIFICATION.md @@ -1,6 +1,8 @@ # Amazon Inspector Specification -This document contains the specification for the *Amazon Inspector Basics Scenario*, based on the implemented Java code examples in `javav2/example_code/inspector/`. The specification describes the actual code example scenario that demonstrates Amazon Inspector V2 vulnerability management capabilities using the AWS SDK for Java V2. +This document contains the specification for the *Amazon Inspector Basics Scenario*, based on the implemented Java code examples in `javav2/example_code/inspector/`. + +The specification describes the actual code example scenario that demonstrates Amazon Inspector V2 vulnerability management capabilities using the AWS SDK for Java V2. ### Relevant documentation From afdd1033e6e9bf537e2525666f65be50aef0ac08 Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Mon, 24 Nov 2025 14:27:00 -0500 Subject: [PATCH 11/11] fixed a issue --- .doc_gen/metadata/inspector_metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.doc_gen/metadata/inspector_metadata.yaml b/.doc_gen/metadata/inspector_metadata.yaml index 094257f5d5f..aa5a4a3f507 100644 --- a/.doc_gen/metadata/inspector_metadata.yaml +++ b/.doc_gen/metadata/inspector_metadata.yaml @@ -136,7 +136,7 @@ inspector_ListFilters: inspector_Scenario: synopsis_list: - Check Inspector account status. - - Ensure Inspector is enabled + - Ensure Inspector is enabled. - Analyze security findings. - Check scan coverage. - Create a findings filter.