From ebd3e2efbd014043182392b91b39dd459d425119 Mon Sep 17 00:00:00 2001 From: Macdonald Date: Mon, 27 Oct 2025 11:40:02 -0400 Subject: [PATCH 01/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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. From 00db446c906957ba8ed333e7fe79a74270ec386c Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Tue, 2 Dec 2025 10:26:42 -0500 Subject: [PATCH 12/21] updated the Java example --- .../src/main/java/com/java/inspector/HelloInspector.java | 2 +- .../main/java/com/java/inspector/InspectorScenario.java | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) 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 bed9d6e69a4..821358d17a8 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 @@ -51,7 +51,7 @@ public static void main(String[] args) { showUsageTotals(inspectorClient); System.out.println(); - System.out.println("Hello Inspector example completed successfully!"); + System.out.println("The Hello Inspector example completed successfully!"); } catch (Inspector2Exception e) { System.err.println(" Error: " + e.getMessage()); 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 c145cee420f..21a9e3a3fe8 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 @@ -23,12 +23,11 @@ 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("Amazon Inspector Basics Scenario"); System.out.println(DASHES); System.out.println(); @@ -71,7 +70,7 @@ by Amazon Web Services (AWS) that helps improve the security inspectorActions.enableInspector(inspectorClient, null); } catch (Exception e) { - System.err.println(" Could not create example filter: " + e.getMessage()); + System.err.println("Could not create an example filter: " + e.getMessage()); } waitForInputToContinue(scanner); @@ -84,7 +83,7 @@ by Amazon Web Services (AWS) that helps improve the security inspectorActions.listFindings(inspectorClient, maxResults, null); } catch (Exception e) { - System.err.println(" Could not create example filter: " + e.getMessage()); + System.err.println("Could not create example filter: " + e.getMessage()); } System.out.println(); waitForInputToContinue(scanner); From be404ef3487d8da199b15c94daa4371dd7a37ec5 Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Thu, 4 Dec 2025 06:44:22 -0500 Subject: [PATCH 13/21] updated the Java example --- .../src/main/java/com/java/inspector/HelloInspector.java | 2 +- 1 file changed, 1 insertion(+), 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 821358d17a8..6ee2569938d 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 @@ -51,7 +51,7 @@ public static void main(String[] args) { showUsageTotals(inspectorClient); System.out.println(); - System.out.println("The Hello Inspector example completed successfully!"); + System.out.println("The Hello Inspector example completed successfully."); } catch (Inspector2Exception e) { System.err.println(" Error: " + e.getMessage()); From d389a940630df353217edb6a5016c5a52eec9670 Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Thu, 4 Dec 2025 07:51:10 -0500 Subject: [PATCH 14/21] updated Java file --- .../src/main/java/com/java/inspector/InspectorScenario.java | 1 - 1 file changed, 1 deletion(-) 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 21a9e3a3fe8..00caece51a3 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 @@ -21,7 +21,6 @@ public class InspectorScenario { static Scanner scanner = new Scanner(System.in); public static void main(String[] args) { - InspectorActions inspectorActions = new InspectorActions(); Inspector2Client inspectorClient = Inspector2Client.builder() .region(Region.US_EAST_1) From 9266a0b53d4c32a9c9e8318c684bac191c6a3919 Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Thu, 4 Dec 2025 08:42:40 -0500 Subject: [PATCH 15/21] updated spec --- javav2/example_code/inspector/pom.xml | 9 --------- scenarios/basics/inspector/SPECIFICATION.md | 15 ++++++++------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/javav2/example_code/inspector/pom.xml b/javav2/example_code/inspector/pom.xml index f559deabe0f..398cd5a9e2e 100644 --- a/javav2/example_code/inspector/pom.xml +++ b/javav2/example_code/inspector/pom.xml @@ -101,18 +101,9 @@ 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/scenarios/basics/inspector/SPECIFICATION.md b/scenarios/basics/inspector/SPECIFICATION.md index 51eece5c95f..8a0d2f44aed 100644 --- a/scenarios/basics/inspector/SPECIFICATION.md +++ b/scenarios/basics/inspector/SPECIFICATION.md @@ -1,6 +1,11 @@ # Amazon Inspector Specification -This document contains a draft proposal for an *Amazon Inspector Basics Scenario*, generated by the Code Examples SpecGen AI tool. The specifications describe a potential code example scenario based on research, usage data, service information, and AI-assistance. The following should be reviewed for accuracy and correctness before proceeding on to a final specification. +## Overview +This SDK Basics scenario demonstrates how to interact with Amazon Inspector using an AWS SDK. +It demonstrates various tasks such as checking the status of an Inspector account, enabling Inspector for resource types, showing coverage information, and so on. + +## Resources +This Basics scenario does not require any additional AWS resources. ### Relevant documentation @@ -18,13 +23,9 @@ This document contains a draft proposal for an *Amazon Inspector Basics Scenario * [ListCoverage](https://docs.aws.amazon.com/inspector/v2/APIReference/API_ListCoverage.html) * [Disable](https://docs.aws.amazon.com/inspector/v2/APIReference/API_Disable.html) -## Proposed example structure - -The output below demonstrates how this example would run for the customer. It includes a Hello service example (included for all services), and the scenario description. The scenario code would also be presented as Action snippets, with a code snippet for each SDK action. - -### Hello +## Hello Amazon Inspector -The Hello example is a separate runnable example. - Set up the Inspector service client - Check the current account status for Inspector - Display available scan types and regions +The Hello example is a separate runnable example. - Set up the Inspector service client, checks the current account status for Inspector and displays available scan types. ## Scenario From f0755a2b2469f6baa4bc6bcead2ddeca18040abc Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Thu, 4 Dec 2025 09:02:09 -0500 Subject: [PATCH 16/21] updated spec --- .../com/java/inspector/InspectorScenario.java | 4 +- scenarios/basics/inspector/SPECIFICATION.md | 65 +++++++++++++------ 2 files changed, 48 insertions(+), 21 deletions(-) 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 00caece51a3..c15a1f5eba4 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 @@ -155,9 +155,9 @@ by Amazon Web Services (AWS) that helps improve the security } System.out.println(); - System.out.println("🎉 Inspector Basics scenario completed successfully!"); + System.out.println(" Inspector Basics scenario completed successfully!"); System.out.println(); - System.out.println("📚 What you learned:"); + 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"); diff --git a/scenarios/basics/inspector/SPECIFICATION.md b/scenarios/basics/inspector/SPECIFICATION.md index 8a0d2f44aed..4e7848781c1 100644 --- a/scenarios/basics/inspector/SPECIFICATION.md +++ b/scenarios/basics/inspector/SPECIFICATION.md @@ -25,38 +25,65 @@ This Basics scenario does not require any additional AWS resources. ## Hello Amazon Inspector -The Hello example is a separate runnable example. - Set up the Inspector service client, checks the current account status for Inspector and displays available scan types. +The Hello example is intended for users not familiar with this service to easily get up and running. It sets up the Inspector service client, checks the current account status for Inspector and displays available scan types. ## Scenario -#### Setup +## Scenario + +This scenario demonstrates the basic usage of **Amazon Inspector** using a Java program. It focuses on checking account status, enabling Inspector, listing findings, reviewing coverage, and managing filters. + +--- + +### Setup + +* Check Amazon Inspector account status +* Enable Inspector for available resource types (if not already enabled) +* Display account status summary + +--- -* Enable Amazon Inspector for the account -* Verify Inspector is successfully activated -* Display account status and enabled scan types +### Coverage Assessment -#### Coverage Assessment +* List coverage details for scanned resources +* Display overall coverage statistics +* Review scan status for resources (general overview) -* List coverage statistics for EC2 instances, ECR repositories, and Lambda functions -* Display resource coverage details -* Show scanning status for different resource types +--- -#### Findings Management +### Findings Management * List security findings across all resource types -* Filter findings by severity level (CRITICAL, HIGH, MEDIUM, LOW) -* Retrieve detailed information for specific findings +* Create an example filter to suppress low-severity findings +* List existing filters + +--- + +### Usage and Costs + +* Check usage totals and metrics for Inspector +* Review coverage statistics + +--- + +### Notes + +* The program **does not retrieve detailed vulnerability (CVE) information**. +* Resource-specific filtering (e.g., EC2, ECR, Lambda) is **not implemented**. +* Cleanup (disabling Inspector) is **not performed**. -#### Vulnerability Analysis +--- -* Display vulnerability details including CVE information -* Show affected resources and remediation guidance -* Filter findings by resource type (EC2, ECR, Lambda) +### Outcome -#### Cleanup +By following this scenario, users learn how to: -* Optionally disable Inspector scanning (with user confirmation) -* Display final account status +* Check Inspector account status and configuration +* Enable Inspector for different resource types +* List and analyze security findings +* Monitor scan coverage +* Create and manage filters +* Track usage and coverage statistics ## Errors From 4d208a993ca52316c7f2d8d1788d1e15e396975d Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Thu, 4 Dec 2025 09:03:00 -0500 Subject: [PATCH 17/21] updated spec --- scenarios/basics/inspector/SPECIFICATION.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/scenarios/basics/inspector/SPECIFICATION.md b/scenarios/basics/inspector/SPECIFICATION.md index 4e7848781c1..d55b2891ead 100644 --- a/scenarios/basics/inspector/SPECIFICATION.md +++ b/scenarios/basics/inspector/SPECIFICATION.md @@ -29,8 +29,6 @@ The Hello example is intended for users not familiar with this service to easily ## Scenario -## Scenario - This scenario demonstrates the basic usage of **Amazon Inspector** using a Java program. It focuses on checking account status, enabling Inspector, listing findings, reviewing coverage, and managing filters. --- From 280bf14e5fe945a29e6679b8187d19587ceeb852 Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Thu, 4 Dec 2025 09:11:41 -0500 Subject: [PATCH 18/21] updated spec --- scenarios/basics/inspector/SPECIFICATION.md | 42 +++++++++++++-------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/scenarios/basics/inspector/SPECIFICATION.md b/scenarios/basics/inspector/SPECIFICATION.md index d55b2891ead..574227c335e 100644 --- a/scenarios/basics/inspector/SPECIFICATION.md +++ b/scenarios/basics/inspector/SPECIFICATION.md @@ -85,21 +85,33 @@ By following this scenario, users learn how to: ## 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. | +The Java SDK examples include basic exception handling for each Inspector action. The table below describes the exceptions actually handled in the program for each action. + +| Action | Exception | Handling | +|-------------------------------|---------------------------|--------------------------------------------------------------------------| +| `Enable` | `ValidationException` | Prints a message indicating Inspector may already be enabled. | +| `Enable` | `Inspector2Exception` | Prints AWS service error details and rethrows the exception. | +| `Enable` | `Exception` | Wraps and throws a `RuntimeException` for unexpected errors. | +| `BatchGetAccountStatus` | `Inspector2Exception` | Prints AWS service error details and rethrows the exception. | +| `BatchGetAccountStatus` | `Exception` | Wraps and throws a `RuntimeException` for unexpected errors. | +| `ListFindings` | `ValidationException` | Prints validation error details. | +| `ListFindings` | `Inspector2Exception` | Prints AWS service error details and rethrows the exception. | +| `ListFindings` | `Exception` | Wraps and throws a `RuntimeException` for unexpected errors. | +| `ListCoverage` | `ValidationException` | Prints validation error details. | +| `ListCoverage` | `Inspector2Exception` | Prints AWS service error details and rethrows the exception. | +| `ListCoverage` | `Exception` | Wraps and throws a `RuntimeException` for unexpected errors. | +| `ListCoverageStatistics` | `ValidationException` | Prints validation error details. | +| `ListCoverageStatistics` | `Inspector2Exception` | Prints AWS service error details and rethrows the exception. | +| `ListCoverageStatistics` | `Exception` | Wraps and throws a `RuntimeException` for unexpected errors. | +| `ListUsageTotals` | `ValidationException` | Prints validation error details. | +| `ListUsageTotals` | `Inspector2Exception` | Prints AWS service error details and rethrows the exception. | +| `ListUsageTotals` | `Exception` | Wraps and throws a `RuntimeException` for unexpected errors. | +| `CreateFilter` | `Inspector2Exception` | Prints AWS service error details and rethrows the exception. | +| `CreateFilter` | `Exception` | Prints unexpected error message and rethrows the exception. | +| `ListFilters` | `Inspector2Exception` | Prints AWS service error details and rethrows the exception. | +| `ListFilters` | `Exception` | Prints unexpected error message and rethrows the exception. | +| `getAccountStatus` | `Inspector2Exception` | Prints AWS service error details and rethrows the exception. | +| `getAccountStatus` | `Exception` | Wraps and throws a `RuntimeException` for unexpected errors. | ## Metadata From 8a447b3195c6288522ecdff0b2bce537a0d862db Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Thu, 4 Dec 2025 09:40:00 -0500 Subject: [PATCH 19/21] updated spec --- scenarios/basics/inspector/SPECIFICATION.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/scenarios/basics/inspector/SPECIFICATION.md b/scenarios/basics/inspector/SPECIFICATION.md index 574227c335e..6b5cee7314e 100644 --- a/scenarios/basics/inspector/SPECIFICATION.md +++ b/scenarios/basics/inspector/SPECIFICATION.md @@ -115,13 +115,14 @@ The Java SDK examples include basic exception handling for each Inspector action ## 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 | - +| Action / Scenario | Metadata File | Metadata Key | +|-----------------------------------------|------------------------|-------------------------------| +| `Enable` | inspector_metadata.yaml | inspector_EnableInspector | +| `BatchGetAccountStatus` | inspector_metadata.yaml | inspector_GetAccountStatus | +| `ListFindings` | inspector_metadata.yaml | inspector_ListFindings | +| `ListCoverage` | inspector_metadata.yaml | inspector_ListCoverage | +| `ListCoverageStatistics` | inspector_metadata.yaml | inspector_ListCoverageStatistics | +| `ListUsageTotals` | inspector_metadata.yaml | inspector_ListUsageTotals | +| `CreateFilter` | inspector_metadata.yaml | inspector_CreateFilter | +| `ListFilters` | inspector_metadata.yaml | inspector_ListFilters | +| `Amazon Inspector Basics Scenario` | inspector_metadata.yaml | inspector_Scenario | From 4f43876093e27705220693782a8cc7e257c62b27 Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Thu, 4 Dec 2025 09:53:07 -0500 Subject: [PATCH 20/21] updated Readme --- javav2/example_code/inspector/README.md | 122 ++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 javav2/example_code/inspector/README.md diff --git a/javav2/example_code/inspector/README.md b/javav2/example_code/inspector/README.md new file mode 100644 index 00000000000..9b15b1af9d3 --- /dev/null +++ b/javav2/example_code/inspector/README.md @@ -0,0 +1,122 @@ +# Amazon Inspector code examples for the SDK for Java 2.x + +## Overview + +Shows how to use the AWS SDK for Java 2.x to work with Amazon Inspector. + + + + +_Amazon Inspector _ + +## ⚠ Important + +* Running this code might result in charges to your AWS account. For more details, see [AWS Pricing](https://aws.amazon.com/pricing/) and [Free Tier](https://aws.amazon.com/free/). +* Running the tests might result in charges to your AWS account. +* We recommend that you grant your code least privilege. At most, grant only the minimum permissions required to perform the task. For more information, see [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege). +* This code is not tested in every AWS Region. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services). + + + + +## Code examples + +### Prerequisites + +For prerequisites, see the [README](../../README.md#Prerequisites) in the `javav2` folder. + + + + + +### Get started + +- [Hello Amazon Inspector](src/main/java/com/java/inspector/HelloInspector.java#L24) (`BatchGetAccountStatus`) + + +### Basics + +Code examples that show you how to perform the essential operations within a service. + +- [Learn the basics](src/main/java/com/java/inspector/InspectorScenario.java) + + +### Single actions + +Code excerpts that show you how to call individual service functions. + +- [BatchGetAccountStatus](src/main/java/com/java/inspector/InspectorActions.java#L194) +- [BatchGetFindingDetails](src/main/java/com/java/inspector/InspectorActions.java#L194) +- [CreateFilter](src/main/java/com/java/inspector/InspectorActions.java#L290) +- [Enable](src/main/java/com/java/inspector/InspectorActions.java#L21) +- [ListCoverage](src/main/java/com/java/inspector/InspectorActions.java#L415) +- [ListCoverageStatistics](src/main/java/com/java/inspector/InspectorActions.java#L72) +- [ListFindings](src/main/java/com/java/inspector/InspectorActions.java#L340) +- [ListUsageTotals](src/main/java/com/java/inspector/InspectorActions.java#L122) +- [inspector_ListFilters](src/main/java/com/java/inspector/InspectorActions.java#L235) + + + + + +## Run the examples + +### Instructions + + + + + +#### Hello Amazon Inspector + +This example shows you how to get started using Amazon Inspector. + + +#### Learn the basics + +This example shows you how to do the following: + +- 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. + + + + + + + + + +### Tests + +⚠ Running tests might result in charges to your AWS account. + + +To find instructions for running these tests, see the [README](../../README.md#Tests) +in the `javav2` folder. + + + + + + +## Additional resources + +- [Amazon Inspector User Guide](https://docs.aws.amazon.com/inspector/latest/user/what-is-inspector.html) +- [Amazon Inspector API Reference](https://docs.aws.amazon.com/inspector/latest/APIReference/Welcome.html) +- [SDK for Java 2.x Amazon Inspector reference](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/inspector/package-summary.html) + + + + +--- + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 From 9fc0201c4959103e73c46cddf334a5d619b94bf8 Mon Sep 17 00:00:00 2001 From: Scott Macdonald Date: Thu, 4 Dec 2025 10:01:18 -0500 Subject: [PATCH 21/21] updated Readme --- javav2/example_code/iotsitewise/README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/javav2/example_code/iotsitewise/README.md b/javav2/example_code/iotsitewise/README.md index 9ccd8726a4c..901d006cc21 100644 --- a/javav2/example_code/iotsitewise/README.md +++ b/javav2/example_code/iotsitewise/README.md @@ -45,17 +45,17 @@ Code examples that show you how to perform the essential operations within a ser Code excerpts that show you how to call individual service functions. -- [BatchPutAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L169) -- [CreateAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L138) -- [CreateAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L88) -- [CreateGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L378) -- [DeleteAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L293) -- [DeleteAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L320) -- [DeleteGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L423) -- [DescribeAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L264) -- [DescribeGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L450) -- [GetAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L233) -- [ListAssetModels](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L347) +- [BatchPutAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L168) +- [CreateAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L137) +- [CreateAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L87) +- [CreateGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L377) +- [DeleteAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L292) +- [DeleteAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L319) +- [DeleteGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L422) +- [DescribeAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L263) +- [DescribeGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L449) +- [GetAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L232) +- [ListAssetModels](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L346)