From c5dc054be6329129151ead323ef84c894e95b6ce Mon Sep 17 00:00:00 2001 From: awstools Date: Tue, 11 Jun 2024 18:28:57 +0000 Subject: [PATCH] feat(client-accessanalyzer): IAM Access Analyzer now provides policy recommendations to help resolve unused permissions for IAM roles and users. Additionally, IAM Access Analyzer now extends its custom policy checks to detect when IAM policies grant public access or access to critical resources ahead of deployments. --- clients/client-accessanalyzer/README.md | 24 + .../src/AccessAnalyzer.ts | 69 ++ .../src/AccessAnalyzerClient.ts | 18 + .../commands/CheckAccessNotGrantedCommand.ts | 5 +- .../commands/CheckNoPublicAccessCommand.ts | 114 +++ .../GenerateFindingRecommendationCommand.ts | 96 +++ .../GetFindingRecommendationCommand.ts | 119 +++ .../src/commands/index.ts | 3 + .../src/models/models_0.ts | 363 ++++++++- .../GetFindingRecommendationPaginator.ts | 24 + .../src/pagination/index.ts | 2 + .../src/protocols/Aws_restJson1.ts | 191 +++++ .../aws-models/accessanalyzer.json | 749 +++++++++++++++++- 13 files changed, 1766 insertions(+), 11 deletions(-) create mode 100644 clients/client-accessanalyzer/src/commands/CheckNoPublicAccessCommand.ts create mode 100644 clients/client-accessanalyzer/src/commands/GenerateFindingRecommendationCommand.ts create mode 100644 clients/client-accessanalyzer/src/commands/GetFindingRecommendationCommand.ts create mode 100644 clients/client-accessanalyzer/src/pagination/GetFindingRecommendationPaginator.ts diff --git a/clients/client-accessanalyzer/README.md b/clients/client-accessanalyzer/README.md index d6e86b46680f..eca46c963871 100644 --- a/clients/client-accessanalyzer/README.md +++ b/clients/client-accessanalyzer/README.md @@ -257,6 +257,14 @@ CheckNoNewAccess [Command API Reference](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/accessanalyzer/command/CheckNoNewAccessCommand/) / [Input](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-accessanalyzer/Interface/CheckNoNewAccessCommandInput/) / [Output](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-accessanalyzer/Interface/CheckNoNewAccessCommandOutput/) + +
+ +CheckNoPublicAccess + + +[Command API Reference](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/accessanalyzer/command/CheckNoPublicAccessCommand/) / [Input](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-accessanalyzer/Interface/CheckNoPublicAccessCommandInput/) / [Output](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-accessanalyzer/Interface/CheckNoPublicAccessCommandOutput/) +
@@ -297,6 +305,14 @@ DeleteArchiveRule [Command API Reference](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/accessanalyzer/command/DeleteArchiveRuleCommand/) / [Input](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-accessanalyzer/Interface/DeleteArchiveRuleCommandInput/) / [Output](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-accessanalyzer/Interface/DeleteArchiveRuleCommandOutput/) +
+
+ +GenerateFindingRecommendation + + +[Command API Reference](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/accessanalyzer/command/GenerateFindingRecommendationCommand/) / [Input](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-accessanalyzer/Interface/GenerateFindingRecommendationCommandInput/) / [Output](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-accessanalyzer/Interface/GenerateFindingRecommendationCommandOutput/) +
@@ -337,6 +353,14 @@ GetFinding [Command API Reference](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/accessanalyzer/command/GetFindingCommand/) / [Input](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-accessanalyzer/Interface/GetFindingCommandInput/) / [Output](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-accessanalyzer/Interface/GetFindingCommandOutput/) +
+
+ +GetFindingRecommendation + + +[Command API Reference](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/accessanalyzer/command/GetFindingRecommendationCommand/) / [Input](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-accessanalyzer/Interface/GetFindingRecommendationCommandInput/) / [Output](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-accessanalyzer/Interface/GetFindingRecommendationCommandOutput/) +
diff --git a/clients/client-accessanalyzer/src/AccessAnalyzer.ts b/clients/client-accessanalyzer/src/AccessAnalyzer.ts index 66d986899993..f1f46a846879 100644 --- a/clients/client-accessanalyzer/src/AccessAnalyzer.ts +++ b/clients/client-accessanalyzer/src/AccessAnalyzer.ts @@ -23,6 +23,11 @@ import { CheckNoNewAccessCommandInput, CheckNoNewAccessCommandOutput, } from "./commands/CheckNoNewAccessCommand"; +import { + CheckNoPublicAccessCommand, + CheckNoPublicAccessCommandInput, + CheckNoPublicAccessCommandOutput, +} from "./commands/CheckNoPublicAccessCommand"; import { CreateAccessPreviewCommand, CreateAccessPreviewCommandInput, @@ -48,6 +53,11 @@ import { DeleteArchiveRuleCommandInput, DeleteArchiveRuleCommandOutput, } from "./commands/DeleteArchiveRuleCommand"; +import { + GenerateFindingRecommendationCommand, + GenerateFindingRecommendationCommandInput, + GenerateFindingRecommendationCommandOutput, +} from "./commands/GenerateFindingRecommendationCommand"; import { GetAccessPreviewCommand, GetAccessPreviewCommandInput, @@ -65,6 +75,11 @@ import { GetArchiveRuleCommandOutput, } from "./commands/GetArchiveRuleCommand"; import { GetFindingCommand, GetFindingCommandInput, GetFindingCommandOutput } from "./commands/GetFindingCommand"; +import { + GetFindingRecommendationCommand, + GetFindingRecommendationCommandInput, + GetFindingRecommendationCommandOutput, +} from "./commands/GetFindingRecommendationCommand"; import { GetFindingV2Command, GetFindingV2CommandInput, @@ -157,16 +172,19 @@ const commands = { CancelPolicyGenerationCommand, CheckAccessNotGrantedCommand, CheckNoNewAccessCommand, + CheckNoPublicAccessCommand, CreateAccessPreviewCommand, CreateAnalyzerCommand, CreateArchiveRuleCommand, DeleteAnalyzerCommand, DeleteArchiveRuleCommand, + GenerateFindingRecommendationCommand, GetAccessPreviewCommand, GetAnalyzedResourceCommand, GetAnalyzerCommand, GetArchiveRuleCommand, GetFindingCommand, + GetFindingRecommendationCommand, GetFindingV2Command, GetGeneratedPolicyCommand, ListAccessPreviewFindingsCommand, @@ -256,6 +274,23 @@ export interface AccessAnalyzer { cb: (err: any, data?: CheckNoNewAccessCommandOutput) => void ): void; + /** + * @see {@link CheckNoPublicAccessCommand} + */ + checkNoPublicAccess( + args: CheckNoPublicAccessCommandInput, + options?: __HttpHandlerOptions + ): Promise; + checkNoPublicAccess( + args: CheckNoPublicAccessCommandInput, + cb: (err: any, data?: CheckNoPublicAccessCommandOutput) => void + ): void; + checkNoPublicAccess( + args: CheckNoPublicAccessCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: CheckNoPublicAccessCommandOutput) => void + ): void; + /** * @see {@link CreateAccessPreviewCommand} */ @@ -335,6 +370,23 @@ export interface AccessAnalyzer { cb: (err: any, data?: DeleteArchiveRuleCommandOutput) => void ): void; + /** + * @see {@link GenerateFindingRecommendationCommand} + */ + generateFindingRecommendation( + args: GenerateFindingRecommendationCommandInput, + options?: __HttpHandlerOptions + ): Promise; + generateFindingRecommendation( + args: GenerateFindingRecommendationCommandInput, + cb: (err: any, data?: GenerateFindingRecommendationCommandOutput) => void + ): void; + generateFindingRecommendation( + args: GenerateFindingRecommendationCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: GenerateFindingRecommendationCommandOutput) => void + ): void; + /** * @see {@link GetAccessPreviewCommand} */ @@ -405,6 +457,23 @@ export interface AccessAnalyzer { cb: (err: any, data?: GetFindingCommandOutput) => void ): void; + /** + * @see {@link GetFindingRecommendationCommand} + */ + getFindingRecommendation( + args: GetFindingRecommendationCommandInput, + options?: __HttpHandlerOptions + ): Promise; + getFindingRecommendation( + args: GetFindingRecommendationCommandInput, + cb: (err: any, data?: GetFindingRecommendationCommandOutput) => void + ): void; + getFindingRecommendation( + args: GetFindingRecommendationCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: GetFindingRecommendationCommandOutput) => void + ): void; + /** * @see {@link GetFindingV2Command} */ diff --git a/clients/client-accessanalyzer/src/AccessAnalyzerClient.ts b/clients/client-accessanalyzer/src/AccessAnalyzerClient.ts index 662be819eef2..ed2843e94de4 100644 --- a/clients/client-accessanalyzer/src/AccessAnalyzerClient.ts +++ b/clients/client-accessanalyzer/src/AccessAnalyzerClient.ts @@ -63,6 +63,10 @@ import { CheckAccessNotGrantedCommandOutput, } from "./commands/CheckAccessNotGrantedCommand"; import { CheckNoNewAccessCommandInput, CheckNoNewAccessCommandOutput } from "./commands/CheckNoNewAccessCommand"; +import { + CheckNoPublicAccessCommandInput, + CheckNoPublicAccessCommandOutput, +} from "./commands/CheckNoPublicAccessCommand"; import { CreateAccessPreviewCommandInput, CreateAccessPreviewCommandOutput, @@ -71,6 +75,10 @@ import { CreateAnalyzerCommandInput, CreateAnalyzerCommandOutput } from "./comma import { CreateArchiveRuleCommandInput, CreateArchiveRuleCommandOutput } from "./commands/CreateArchiveRuleCommand"; import { DeleteAnalyzerCommandInput, DeleteAnalyzerCommandOutput } from "./commands/DeleteAnalyzerCommand"; import { DeleteArchiveRuleCommandInput, DeleteArchiveRuleCommandOutput } from "./commands/DeleteArchiveRuleCommand"; +import { + GenerateFindingRecommendationCommandInput, + GenerateFindingRecommendationCommandOutput, +} from "./commands/GenerateFindingRecommendationCommand"; import { GetAccessPreviewCommandInput, GetAccessPreviewCommandOutput } from "./commands/GetAccessPreviewCommand"; import { GetAnalyzedResourceCommandInput, @@ -79,6 +87,10 @@ import { import { GetAnalyzerCommandInput, GetAnalyzerCommandOutput } from "./commands/GetAnalyzerCommand"; import { GetArchiveRuleCommandInput, GetArchiveRuleCommandOutput } from "./commands/GetArchiveRuleCommand"; import { GetFindingCommandInput, GetFindingCommandOutput } from "./commands/GetFindingCommand"; +import { + GetFindingRecommendationCommandInput, + GetFindingRecommendationCommandOutput, +} from "./commands/GetFindingRecommendationCommand"; import { GetFindingV2CommandInput, GetFindingV2CommandOutput } from "./commands/GetFindingV2Command"; import { GetGeneratedPolicyCommandInput, GetGeneratedPolicyCommandOutput } from "./commands/GetGeneratedPolicyCommand"; import { @@ -131,16 +143,19 @@ export type ServiceInputTypes = | CancelPolicyGenerationCommandInput | CheckAccessNotGrantedCommandInput | CheckNoNewAccessCommandInput + | CheckNoPublicAccessCommandInput | CreateAccessPreviewCommandInput | CreateAnalyzerCommandInput | CreateArchiveRuleCommandInput | DeleteAnalyzerCommandInput | DeleteArchiveRuleCommandInput + | GenerateFindingRecommendationCommandInput | GetAccessPreviewCommandInput | GetAnalyzedResourceCommandInput | GetAnalyzerCommandInput | GetArchiveRuleCommandInput | GetFindingCommandInput + | GetFindingRecommendationCommandInput | GetFindingV2CommandInput | GetGeneratedPolicyCommandInput | ListAccessPreviewFindingsCommandInput @@ -168,16 +183,19 @@ export type ServiceOutputTypes = | CancelPolicyGenerationCommandOutput | CheckAccessNotGrantedCommandOutput | CheckNoNewAccessCommandOutput + | CheckNoPublicAccessCommandOutput | CreateAccessPreviewCommandOutput | CreateAnalyzerCommandOutput | CreateArchiveRuleCommandOutput | DeleteAnalyzerCommandOutput | DeleteArchiveRuleCommandOutput + | GenerateFindingRecommendationCommandOutput | GetAccessPreviewCommandOutput | GetAnalyzedResourceCommandOutput | GetAnalyzerCommandOutput | GetArchiveRuleCommandOutput | GetFindingCommandOutput + | GetFindingRecommendationCommandOutput | GetFindingV2CommandOutput | GetGeneratedPolicyCommandOutput | ListAccessPreviewFindingsCommandOutput diff --git a/clients/client-accessanalyzer/src/commands/CheckAccessNotGrantedCommand.ts b/clients/client-accessanalyzer/src/commands/CheckAccessNotGrantedCommand.ts index d196721dea2c..edc5afa2ffeb 100644 --- a/clients/client-accessanalyzer/src/commands/CheckAccessNotGrantedCommand.ts +++ b/clients/client-accessanalyzer/src/commands/CheckAccessNotGrantedCommand.ts @@ -43,7 +43,10 @@ export interface CheckAccessNotGrantedCommandOutput extends CheckAccessNotGrante * policyDocument: "STRING_VALUE", // required * access: [ // AccessList // required * { // Access - * actions: [ // ActionsList // required + * actions: [ // ActionsList + * "STRING_VALUE", + * ], + * resources: [ // ResourcesList * "STRING_VALUE", * ], * }, diff --git a/clients/client-accessanalyzer/src/commands/CheckNoPublicAccessCommand.ts b/clients/client-accessanalyzer/src/commands/CheckNoPublicAccessCommand.ts new file mode 100644 index 000000000000..fbd8f305e8f4 --- /dev/null +++ b/clients/client-accessanalyzer/src/commands/CheckNoPublicAccessCommand.ts @@ -0,0 +1,114 @@ +// smithy-typescript generated code +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { getSerdePlugin } from "@smithy/middleware-serde"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +import { AccessAnalyzerClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../AccessAnalyzerClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { + CheckNoPublicAccessRequest, + CheckNoPublicAccessRequestFilterSensitiveLog, + CheckNoPublicAccessResponse, +} from "../models/models_0"; +import { de_CheckNoPublicAccessCommand, se_CheckNoPublicAccessCommand } from "../protocols/Aws_restJson1"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link CheckNoPublicAccessCommand}. + */ +export interface CheckNoPublicAccessCommandInput extends CheckNoPublicAccessRequest {} +/** + * @public + * + * The output of {@link CheckNoPublicAccessCommand}. + */ +export interface CheckNoPublicAccessCommandOutput extends CheckNoPublicAccessResponse, __MetadataBearer {} + +/** + *

Checks whether a resource policy can grant public access to the specified resource + * type.

+ * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { AccessAnalyzerClient, CheckNoPublicAccessCommand } from "@aws-sdk/client-accessanalyzer"; // ES Modules import + * // const { AccessAnalyzerClient, CheckNoPublicAccessCommand } = require("@aws-sdk/client-accessanalyzer"); // CommonJS import + * const client = new AccessAnalyzerClient(config); + * const input = { // CheckNoPublicAccessRequest + * policyDocument: "STRING_VALUE", // required + * resourceType: "STRING_VALUE", // required + * }; + * const command = new CheckNoPublicAccessCommand(input); + * const response = await client.send(command); + * // { // CheckNoPublicAccessResponse + * // result: "STRING_VALUE", + * // message: "STRING_VALUE", + * // reasons: [ // ReasonSummaryList + * // { // ReasonSummary + * // description: "STRING_VALUE", + * // statementIndex: Number("int"), + * // statementId: "STRING_VALUE", + * // }, + * // ], + * // }; + * + * ``` + * + * @param CheckNoPublicAccessCommandInput - {@link CheckNoPublicAccessCommandInput} + * @returns {@link CheckNoPublicAccessCommandOutput} + * @see {@link CheckNoPublicAccessCommandInput} for command's `input` shape. + * @see {@link CheckNoPublicAccessCommandOutput} for command's `response` shape. + * @see {@link AccessAnalyzerClientResolvedConfig | config} for AccessAnalyzerClient's `config` shape. + * + * @throws {@link AccessDeniedException} (client fault) + *

You do not have sufficient access to perform this action.

+ * + * @throws {@link InternalServerException} (server fault) + *

Internal server error.

+ * + * @throws {@link InvalidParameterException} (client fault) + *

The specified parameter is invalid.

+ * + * @throws {@link ThrottlingException} (client fault) + *

Throttling limit exceeded error.

+ * + * @throws {@link UnprocessableEntityException} (client fault) + *

The specified entity could not be processed.

+ * + * @throws {@link ValidationException} (client fault) + *

Validation exception error.

+ * + * @throws {@link AccessAnalyzerServiceException} + *

Base exception class for all service exceptions from AccessAnalyzer service.

+ * + * @public + */ +export class CheckNoPublicAccessCommand extends $Command + .classBuilder< + CheckNoPublicAccessCommandInput, + CheckNoPublicAccessCommandOutput, + AccessAnalyzerClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep({ + ...commonParams, + }) + .m(function (this: any, Command: any, cs: any, config: AccessAnalyzerClientResolvedConfig, o: any) { + return [ + getSerdePlugin(config, this.serialize, this.deserialize), + getEndpointPlugin(config, Command.getEndpointParameterInstructions()), + ]; + }) + .s("AccessAnalyzer", "CheckNoPublicAccess", {}) + .n("AccessAnalyzerClient", "CheckNoPublicAccessCommand") + .f(CheckNoPublicAccessRequestFilterSensitiveLog, void 0) + .ser(se_CheckNoPublicAccessCommand) + .de(de_CheckNoPublicAccessCommand) + .build() {} diff --git a/clients/client-accessanalyzer/src/commands/GenerateFindingRecommendationCommand.ts b/clients/client-accessanalyzer/src/commands/GenerateFindingRecommendationCommand.ts new file mode 100644 index 000000000000..e35193d7c6b2 --- /dev/null +++ b/clients/client-accessanalyzer/src/commands/GenerateFindingRecommendationCommand.ts @@ -0,0 +1,96 @@ +// smithy-typescript generated code +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { getSerdePlugin } from "@smithy/middleware-serde"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +import { AccessAnalyzerClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../AccessAnalyzerClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { GenerateFindingRecommendationRequest } from "../models/models_0"; +import { + de_GenerateFindingRecommendationCommand, + se_GenerateFindingRecommendationCommand, +} from "../protocols/Aws_restJson1"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link GenerateFindingRecommendationCommand}. + */ +export interface GenerateFindingRecommendationCommandInput extends GenerateFindingRecommendationRequest {} +/** + * @public + * + * The output of {@link GenerateFindingRecommendationCommand}. + */ +export interface GenerateFindingRecommendationCommandOutput extends __MetadataBearer {} + +/** + *

Creates a recommendation for an unused permissions finding.

+ * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { AccessAnalyzerClient, GenerateFindingRecommendationCommand } from "@aws-sdk/client-accessanalyzer"; // ES Modules import + * // const { AccessAnalyzerClient, GenerateFindingRecommendationCommand } = require("@aws-sdk/client-accessanalyzer"); // CommonJS import + * const client = new AccessAnalyzerClient(config); + * const input = { // GenerateFindingRecommendationRequest + * analyzerArn: "STRING_VALUE", // required + * id: "STRING_VALUE", // required + * }; + * const command = new GenerateFindingRecommendationCommand(input); + * const response = await client.send(command); + * // {}; + * + * ``` + * + * @param GenerateFindingRecommendationCommandInput - {@link GenerateFindingRecommendationCommandInput} + * @returns {@link GenerateFindingRecommendationCommandOutput} + * @see {@link GenerateFindingRecommendationCommandInput} for command's `input` shape. + * @see {@link GenerateFindingRecommendationCommandOutput} for command's `response` shape. + * @see {@link AccessAnalyzerClientResolvedConfig | config} for AccessAnalyzerClient's `config` shape. + * + * @throws {@link AccessDeniedException} (client fault) + *

You do not have sufficient access to perform this action.

+ * + * @throws {@link InternalServerException} (server fault) + *

Internal server error.

+ * + * @throws {@link ThrottlingException} (client fault) + *

Throttling limit exceeded error.

+ * + * @throws {@link ValidationException} (client fault) + *

Validation exception error.

+ * + * @throws {@link AccessAnalyzerServiceException} + *

Base exception class for all service exceptions from AccessAnalyzer service.

+ * + * @public + */ +export class GenerateFindingRecommendationCommand extends $Command + .classBuilder< + GenerateFindingRecommendationCommandInput, + GenerateFindingRecommendationCommandOutput, + AccessAnalyzerClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep({ + ...commonParams, + }) + .m(function (this: any, Command: any, cs: any, config: AccessAnalyzerClientResolvedConfig, o: any) { + return [ + getSerdePlugin(config, this.serialize, this.deserialize), + getEndpointPlugin(config, Command.getEndpointParameterInstructions()), + ]; + }) + .s("AccessAnalyzer", "GenerateFindingRecommendation", {}) + .n("AccessAnalyzerClient", "GenerateFindingRecommendationCommand") + .f(void 0, void 0) + .ser(se_GenerateFindingRecommendationCommand) + .de(de_GenerateFindingRecommendationCommand) + .build() {} diff --git a/clients/client-accessanalyzer/src/commands/GetFindingRecommendationCommand.ts b/clients/client-accessanalyzer/src/commands/GetFindingRecommendationCommand.ts new file mode 100644 index 000000000000..ba188e047be2 --- /dev/null +++ b/clients/client-accessanalyzer/src/commands/GetFindingRecommendationCommand.ts @@ -0,0 +1,119 @@ +// smithy-typescript generated code +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { getSerdePlugin } from "@smithy/middleware-serde"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +import { AccessAnalyzerClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../AccessAnalyzerClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { GetFindingRecommendationRequest, GetFindingRecommendationResponse } from "../models/models_0"; +import { de_GetFindingRecommendationCommand, se_GetFindingRecommendationCommand } from "../protocols/Aws_restJson1"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link GetFindingRecommendationCommand}. + */ +export interface GetFindingRecommendationCommandInput extends GetFindingRecommendationRequest {} +/** + * @public + * + * The output of {@link GetFindingRecommendationCommand}. + */ +export interface GetFindingRecommendationCommandOutput extends GetFindingRecommendationResponse, __MetadataBearer {} + +/** + *

Retrieves information about a finding recommendation for the specified analyzer.

+ * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { AccessAnalyzerClient, GetFindingRecommendationCommand } from "@aws-sdk/client-accessanalyzer"; // ES Modules import + * // const { AccessAnalyzerClient, GetFindingRecommendationCommand } = require("@aws-sdk/client-accessanalyzer"); // CommonJS import + * const client = new AccessAnalyzerClient(config); + * const input = { // GetFindingRecommendationRequest + * analyzerArn: "STRING_VALUE", // required + * id: "STRING_VALUE", // required + * maxResults: Number("int"), + * nextToken: "STRING_VALUE", + * }; + * const command = new GetFindingRecommendationCommand(input); + * const response = await client.send(command); + * // { // GetFindingRecommendationResponse + * // startedAt: new Date("TIMESTAMP"), // required + * // completedAt: new Date("TIMESTAMP"), + * // nextToken: "STRING_VALUE", + * // error: { // RecommendationError + * // code: "STRING_VALUE", // required + * // message: "STRING_VALUE", // required + * // }, + * // resourceArn: "STRING_VALUE", // required + * // recommendedSteps: [ // RecommendedStepList + * // { // RecommendedStep Union: only one key present + * // unusedPermissionsRecommendedStep: { // UnusedPermissionsRecommendedStep + * // policyUpdatedAt: new Date("TIMESTAMP"), + * // recommendedAction: "STRING_VALUE", // required + * // recommendedPolicy: "STRING_VALUE", + * // existingPolicyId: "STRING_VALUE", + * // }, + * // }, + * // ], + * // recommendationType: "STRING_VALUE", // required + * // status: "STRING_VALUE", // required + * // }; + * + * ``` + * + * @param GetFindingRecommendationCommandInput - {@link GetFindingRecommendationCommandInput} + * @returns {@link GetFindingRecommendationCommandOutput} + * @see {@link GetFindingRecommendationCommandInput} for command's `input` shape. + * @see {@link GetFindingRecommendationCommandOutput} for command's `response` shape. + * @see {@link AccessAnalyzerClientResolvedConfig | config} for AccessAnalyzerClient's `config` shape. + * + * @throws {@link AccessDeniedException} (client fault) + *

You do not have sufficient access to perform this action.

+ * + * @throws {@link InternalServerException} (server fault) + *

Internal server error.

+ * + * @throws {@link ResourceNotFoundException} (client fault) + *

The specified resource could not be found.

+ * + * @throws {@link ThrottlingException} (client fault) + *

Throttling limit exceeded error.

+ * + * @throws {@link ValidationException} (client fault) + *

Validation exception error.

+ * + * @throws {@link AccessAnalyzerServiceException} + *

Base exception class for all service exceptions from AccessAnalyzer service.

+ * + * @public + */ +export class GetFindingRecommendationCommand extends $Command + .classBuilder< + GetFindingRecommendationCommandInput, + GetFindingRecommendationCommandOutput, + AccessAnalyzerClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep({ + ...commonParams, + }) + .m(function (this: any, Command: any, cs: any, config: AccessAnalyzerClientResolvedConfig, o: any) { + return [ + getSerdePlugin(config, this.serialize, this.deserialize), + getEndpointPlugin(config, Command.getEndpointParameterInstructions()), + ]; + }) + .s("AccessAnalyzer", "GetFindingRecommendation", {}) + .n("AccessAnalyzerClient", "GetFindingRecommendationCommand") + .f(void 0, void 0) + .ser(se_GetFindingRecommendationCommand) + .de(de_GetFindingRecommendationCommand) + .build() {} diff --git a/clients/client-accessanalyzer/src/commands/index.ts b/clients/client-accessanalyzer/src/commands/index.ts index fd5a8ea59add..d9c1e959812a 100644 --- a/clients/client-accessanalyzer/src/commands/index.ts +++ b/clients/client-accessanalyzer/src/commands/index.ts @@ -3,16 +3,19 @@ export * from "./ApplyArchiveRuleCommand"; export * from "./CancelPolicyGenerationCommand"; export * from "./CheckAccessNotGrantedCommand"; export * from "./CheckNoNewAccessCommand"; +export * from "./CheckNoPublicAccessCommand"; export * from "./CreateAccessPreviewCommand"; export * from "./CreateAnalyzerCommand"; export * from "./CreateArchiveRuleCommand"; export * from "./DeleteAnalyzerCommand"; export * from "./DeleteArchiveRuleCommand"; +export * from "./GenerateFindingRecommendationCommand"; export * from "./GetAccessPreviewCommand"; export * from "./GetAnalyzedResourceCommand"; export * from "./GetAnalyzerCommand"; export * from "./GetArchiveRuleCommand"; export * from "./GetFindingCommand"; +export * from "./GetFindingRecommendationCommand"; export * from "./GetFindingV2Command"; export * from "./GetGeneratedPolicyCommand"; export * from "./ListAccessPreviewFindingsCommand"; diff --git a/clients/client-accessanalyzer/src/models/models_0.ts b/clients/client-accessanalyzer/src/models/models_0.ts index 3ef5160ccf52..2661d2c78d8e 100644 --- a/clients/client-accessanalyzer/src/models/models_0.ts +++ b/clients/client-accessanalyzer/src/models/models_0.ts @@ -4,8 +4,8 @@ import { ExceptionOptionType as __ExceptionOptionType, SENSITIVE_STRING } from " import { AccessAnalyzerServiceException as __BaseException } from "./AccessAnalyzerServiceException"; /** - *

Contains information about actions that define permissions to check against a - * policy.

+ *

Contains information about actions and resources that define permissions to check + * against a policy.

* @public */ export interface Access { @@ -14,7 +14,14 @@ export interface Access { * in an IAM policy can be used in the list of actions to check.

* @public */ - actions: string[] | undefined; + actions?: string[]; + + /** + *

A list of resources for the access permissions. Any strings that can be used as a + * resource in an IAM policy can be used in the list of resources to check.

+ * @public + */ + resources?: string[]; } /** @@ -284,6 +291,7 @@ export interface ValidationExceptionField { export const ValidationExceptionReason = { CANNOT_PARSE: "cannotParse", FIELD_VALIDATION_FAILED: "fieldValidationFailed", + NOT_SUPPORTED: "notSupported", OTHER: "other", UNKNOWN_OPERATION: "unknownOperation", } as const; @@ -883,7 +891,11 @@ export interface CheckAccessNotGrantedRequest { /** *

An access object containing the permissions that shouldn't be granted by the specified - * policy.

+ * policy. If only actions are specified, IAM Access Analyzer checks for access of the actions on + * all resources in the policy. If only resources are specified, then IAM Access Analyzer checks + * which actions have access to the specified resources. If both actions and resources are + * specified, then IAM Access Analyzer checks which of the specified actions have access to the + * specified resources.

* @public */ access: Access[] | undefined; @@ -1074,6 +1086,99 @@ export interface CheckNoNewAccessResponse { reasons?: ReasonSummary[]; } +/** + * @public + * @enum + */ +export const AccessCheckResourceType = { + DYNAMODB_STREAM: "AWS::DynamoDB::Stream", + DYNAMODB_TABLE: "AWS::DynamoDB::Table", + EFS_FILESYSTEM: "AWS::EFS::FileSystem", + KINESIS_DATA_STREAM: "AWS::Kinesis::Stream", + KINESIS_STREAM_CONSUMER: "AWS::Kinesis::StreamConsumer", + KMS_KEY: "AWS::KMS::Key", + LAMBDA_FUNCTION: "AWS::Lambda::Function", + OPENSEARCHSERVICE_DOMAIN: "AWS::OpenSearchService::Domain", + ROLE_TRUST: "AWS::IAM::AssumeRolePolicyDocument", + S3EXPRESS_DIRECTORYBUCKET: "AWS::S3Express::DirectoryBucket", + S3_ACCESS_POINT: "AWS::S3::AccessPoint", + S3_BUCKET: "AWS::S3::Bucket", + S3_GLACIER: "AWS::S3::Glacier", + S3_OUTPOSTS_ACCESS_POINT: "AWS::S3Outposts::AccessPoint", + S3_OUTPOSTS_BUCKET: "AWS::S3Outposts::Bucket", + SECRETSMANAGER_SECRET: "AWS::SecretsManager::Secret", + SNS_TOPIC: "AWS::SNS::Topic", + SQS_QUEUE: "AWS::SQS::Queue", +} as const; + +/** + * @public + */ +export type AccessCheckResourceType = (typeof AccessCheckResourceType)[keyof typeof AccessCheckResourceType]; + +/** + * @public + */ +export interface CheckNoPublicAccessRequest { + /** + *

The JSON policy document to evaluate for public access.

+ * @public + */ + policyDocument: string | undefined; + + /** + *

The type of resource to evaluate for public access. For example, to check for public + * access to Amazon S3 buckets, you can choose AWS::S3::Bucket for the resource + * type.

+ *

For resource types not supported as valid values, IAM Access Analyzer will return an + * error.

+ * @public + */ + resourceType: AccessCheckResourceType | undefined; +} + +/** + * @public + * @enum + */ +export const CheckNoPublicAccessResult = { + FAIL: "FAIL", + PASS: "PASS", +} as const; + +/** + * @public + */ +export type CheckNoPublicAccessResult = (typeof CheckNoPublicAccessResult)[keyof typeof CheckNoPublicAccessResult]; + +/** + * @public + */ +export interface CheckNoPublicAccessResponse { + /** + *

The result of the check for public access to the specified resource type. If the result + * is PASS, the policy doesn't allow public access to the specified resource + * type. If the result is FAIL, the policy might allow public access to the + * specified resource type.

+ * @public + */ + result?: CheckNoPublicAccessResult; + + /** + *

The message indicating whether the specified policy allows public access to + * resources.

+ * @public + */ + message?: string; + + /** + *

A list of reasons why the specified resource policy grants public access for the + * resource type.

+ * @public + */ + reasons?: ReasonSummary[]; +} + /** *

The proposed access control configuration for a DynamoDB stream. You can propose a * configuration for a new DynamoDB stream or an existing DynamoDB stream that you own by specifying @@ -2412,6 +2517,24 @@ export interface CreateAccessPreviewResponse { id: string | undefined; } +/** + * @public + */ +export interface GenerateFindingRecommendationRequest { + /** + *

The ARN of + * the analyzer used to generate the finding recommendation.

+ * @public + */ + analyzerArn: string | undefined; + + /** + *

The unique ID for the finding recommendation.

+ * @public + */ + id: string | undefined; +} + /** * @public */ @@ -2848,6 +2971,228 @@ export interface GetFindingResponse { finding?: Finding; } +/** + * @public + */ +export interface GetFindingRecommendationRequest { + /** + *

The ARN of + * the analyzer used to generate the finding recommendation.

+ * @public + */ + analyzerArn: string | undefined; + + /** + *

The unique ID for the finding recommendation.

+ * @public + */ + id: string | undefined; + + /** + *

The maximum number of results to return in the response.

+ * @public + */ + maxResults?: number; + + /** + *

A token used for pagination of results returned.

+ * @public + */ + nextToken?: string; +} + +/** + *

Contains information about the reason that the retrieval of a recommendation for a + * finding failed.

+ * @public + */ +export interface RecommendationError { + /** + *

The error code for a failed retrieval of a recommendation for a finding.

+ * @public + */ + code: string | undefined; + + /** + *

The error message for a failed retrieval of a recommendation for a finding.

+ * @public + */ + message: string | undefined; +} + +/** + * @public + * @enum + */ +export const RecommendationType = { + UNUSED_PERMISSION_RECOMMENDATION: "UnusedPermissionRecommendation", +} as const; + +/** + * @public + */ +export type RecommendationType = (typeof RecommendationType)[keyof typeof RecommendationType]; + +/** + * @public + * @enum + */ +export const RecommendedRemediationAction = { + CREATE_POLICY: "CREATE_POLICY", + DETACH_POLICY: "DETACH_POLICY", +} as const; + +/** + * @public + */ +export type RecommendedRemediationAction = + (typeof RecommendedRemediationAction)[keyof typeof RecommendedRemediationAction]; + +/** + *

Contains information about the action to take for a policy in an unused permissions + * finding.

+ * @public + */ +export interface UnusedPermissionsRecommendedStep { + /** + *

The time at which the existing policy for the unused permissions finding was last + * updated.

+ * @public + */ + policyUpdatedAt?: Date; + + /** + *

A recommendation of whether to create or detach a policy for an unused permissions + * finding.

+ * @public + */ + recommendedAction: RecommendedRemediationAction | undefined; + + /** + *

If the recommended action for the unused permissions finding is to replace the existing + * policy, the contents of the recommended policy to replace the policy specified in the + * existingPolicyId field.

+ * @public + */ + recommendedPolicy?: string; + + /** + *

If the recommended action for the unused permissions finding is to detach a policy, the + * ID of an existing policy to be detached.

+ * @public + */ + existingPolicyId?: string; +} + +/** + *

Contains information about a recommended step for an unused access analyzer + * finding.

+ * @public + */ +export type RecommendedStep = RecommendedStep.UnusedPermissionsRecommendedStepMember | RecommendedStep.$UnknownMember; + +/** + * @public + */ +export namespace RecommendedStep { + /** + *

A recommended step for an unused permissions finding.

+ * @public + */ + export interface UnusedPermissionsRecommendedStepMember { + unusedPermissionsRecommendedStep: UnusedPermissionsRecommendedStep; + $unknown?: never; + } + + /** + * @public + */ + export interface $UnknownMember { + unusedPermissionsRecommendedStep?: never; + $unknown: [string, any]; + } + + export interface Visitor { + unusedPermissionsRecommendedStep: (value: UnusedPermissionsRecommendedStep) => T; + _: (name: string, value: any) => T; + } + + export const visit = (value: RecommendedStep, visitor: Visitor): T => { + if (value.unusedPermissionsRecommendedStep !== undefined) + return visitor.unusedPermissionsRecommendedStep(value.unusedPermissionsRecommendedStep); + return visitor._(value.$unknown[0], value.$unknown[1]); + }; +} + +/** + * @public + * @enum + */ +export const Status = { + FAILED: "FAILED", + IN_PROGRESS: "IN_PROGRESS", + SUCCEEDED: "SUCCEEDED", +} as const; + +/** + * @public + */ +export type Status = (typeof Status)[keyof typeof Status]; + +/** + * @public + */ +export interface GetFindingRecommendationResponse { + /** + *

The time at which the retrieval of the finding recommendation was started.

+ * @public + */ + startedAt: Date | undefined; + + /** + *

The time at which the retrieval of the finding recommendation was completed.

+ * @public + */ + completedAt?: Date; + + /** + *

A token used for pagination of results returned.

+ * @public + */ + nextToken?: string; + + /** + *

Detailed information about the reason that the retrieval of a recommendation for the + * finding failed.

+ * @public + */ + error?: RecommendationError; + + /** + *

The ARN of the resource of the finding.

+ * @public + */ + resourceArn: string | undefined; + + /** + *

A group of recommended steps for the finding.

+ * @public + */ + recommendedSteps?: RecommendedStep[]; + + /** + *

The type of recommendation for the finding.

+ * @public + */ + recommendationType: RecommendationType | undefined; + + /** + *

The status of the retrieval of the finding recommendation.

+ * @public + */ + status: Status | undefined; +} + /** * @public */ @@ -3010,7 +3355,7 @@ export interface UnusedPermissionDetails { serviceNamespace: string | undefined; /** - *

The time at which the permission last accessed.

+ *

The time at which the permission was last accessed.

* @public */ lastAccessed?: Date; @@ -4871,3 +5216,11 @@ export const CheckNoNewAccessRequestFilterSensitiveLog = (obj: CheckNoNewAccessR ...(obj.newPolicyDocument && { newPolicyDocument: SENSITIVE_STRING }), ...(obj.existingPolicyDocument && { existingPolicyDocument: SENSITIVE_STRING }), }); + +/** + * @internal + */ +export const CheckNoPublicAccessRequestFilterSensitiveLog = (obj: CheckNoPublicAccessRequest): any => ({ + ...obj, + ...(obj.policyDocument && { policyDocument: SENSITIVE_STRING }), +}); diff --git a/clients/client-accessanalyzer/src/pagination/GetFindingRecommendationPaginator.ts b/clients/client-accessanalyzer/src/pagination/GetFindingRecommendationPaginator.ts new file mode 100644 index 000000000000..fc4a56ad60e2 --- /dev/null +++ b/clients/client-accessanalyzer/src/pagination/GetFindingRecommendationPaginator.ts @@ -0,0 +1,24 @@ +// smithy-typescript generated code +import { createPaginator } from "@smithy/core"; +import { Paginator } from "@smithy/types"; + +import { AccessAnalyzerClient } from "../AccessAnalyzerClient"; +import { + GetFindingRecommendationCommand, + GetFindingRecommendationCommandInput, + GetFindingRecommendationCommandOutput, +} from "../commands/GetFindingRecommendationCommand"; +import { AccessAnalyzerPaginationConfiguration } from "./Interfaces"; + +/** + * @public + */ +export const paginateGetFindingRecommendation: ( + config: AccessAnalyzerPaginationConfiguration, + input: GetFindingRecommendationCommandInput, + ...rest: any[] +) => Paginator = createPaginator< + AccessAnalyzerPaginationConfiguration, + GetFindingRecommendationCommandInput, + GetFindingRecommendationCommandOutput +>(AccessAnalyzerClient, GetFindingRecommendationCommand, "nextToken", "nextToken", "maxResults"); diff --git a/clients/client-accessanalyzer/src/pagination/index.ts b/clients/client-accessanalyzer/src/pagination/index.ts index 1471f2fa6e4c..0f8821c80ae2 100644 --- a/clients/client-accessanalyzer/src/pagination/index.ts +++ b/clients/client-accessanalyzer/src/pagination/index.ts @@ -1,3 +1,5 @@ +export * from "./GetFindingRecommendationPaginator"; + export * from "./GetFindingV2Paginator"; // smithy-typescript generated code export * from "./Interfaces"; diff --git a/clients/client-accessanalyzer/src/protocols/Aws_restJson1.ts b/clients/client-accessanalyzer/src/protocols/Aws_restJson1.ts index 157b48c203f8..b972f2bb779a 100644 --- a/clients/client-accessanalyzer/src/protocols/Aws_restJson1.ts +++ b/clients/client-accessanalyzer/src/protocols/Aws_restJson1.ts @@ -41,6 +41,10 @@ import { CheckAccessNotGrantedCommandOutput, } from "../commands/CheckAccessNotGrantedCommand"; import { CheckNoNewAccessCommandInput, CheckNoNewAccessCommandOutput } from "../commands/CheckNoNewAccessCommand"; +import { + CheckNoPublicAccessCommandInput, + CheckNoPublicAccessCommandOutput, +} from "../commands/CheckNoPublicAccessCommand"; import { CreateAccessPreviewCommandInput, CreateAccessPreviewCommandOutput, @@ -49,6 +53,10 @@ import { CreateAnalyzerCommandInput, CreateAnalyzerCommandOutput } from "../comm import { CreateArchiveRuleCommandInput, CreateArchiveRuleCommandOutput } from "../commands/CreateArchiveRuleCommand"; import { DeleteAnalyzerCommandInput, DeleteAnalyzerCommandOutput } from "../commands/DeleteAnalyzerCommand"; import { DeleteArchiveRuleCommandInput, DeleteArchiveRuleCommandOutput } from "../commands/DeleteArchiveRuleCommand"; +import { + GenerateFindingRecommendationCommandInput, + GenerateFindingRecommendationCommandOutput, +} from "../commands/GenerateFindingRecommendationCommand"; import { GetAccessPreviewCommandInput, GetAccessPreviewCommandOutput } from "../commands/GetAccessPreviewCommand"; import { GetAnalyzedResourceCommandInput, @@ -57,6 +65,10 @@ import { import { GetAnalyzerCommandInput, GetAnalyzerCommandOutput } from "../commands/GetAnalyzerCommand"; import { GetArchiveRuleCommandInput, GetArchiveRuleCommandOutput } from "../commands/GetArchiveRuleCommand"; import { GetFindingCommandInput, GetFindingCommandOutput } from "../commands/GetFindingCommand"; +import { + GetFindingRecommendationCommandInput, + GetFindingRecommendationCommandOutput, +} from "../commands/GetFindingRecommendationCommand"; import { GetFindingV2CommandInput, GetFindingV2CommandOutput } from "../commands/GetFindingV2Command"; import { GetGeneratedPolicyCommandInput, GetGeneratedPolicyCommandOutput } from "../commands/GetGeneratedPolicyCommand"; import { @@ -135,6 +147,7 @@ import { RdsDbClusterSnapshotConfiguration, RdsDbSnapshotAttributeValue, RdsDbSnapshotConfiguration, + RecommendedStep, ResourceNotFoundException, S3AccessPointConfiguration, S3BucketAclGrantConfiguration, @@ -155,6 +168,7 @@ import { UnusedIamUserAccessKeyDetails, UnusedIamUserPasswordDetails, UnusedPermissionDetails, + UnusedPermissionsRecommendedStep, ValidationException, VpcConfiguration, } from "../models/models_0"; @@ -247,6 +261,29 @@ export const se_CheckNoNewAccessCommand = async ( return b.build(); }; +/** + * serializeAws_restJson1CheckNoPublicAccessCommand + */ +export const se_CheckNoPublicAccessCommand = async ( + input: CheckNoPublicAccessCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const b = rb(input, context); + const headers: any = { + "content-type": "application/json", + }; + b.bp("/policy/check-no-public-access"); + let body: any; + body = JSON.stringify( + take(input, { + policyDocument: [], + resourceType: [], + }) + ); + b.m("POST").h(headers).b(body); + return b.build(); +}; + /** * serializeAws_restJson1CreateAccessPreviewCommand */ @@ -362,6 +399,25 @@ export const se_DeleteArchiveRuleCommand = async ( return b.build(); }; +/** + * serializeAws_restJson1GenerateFindingRecommendationCommand + */ +export const se_GenerateFindingRecommendationCommand = async ( + input: GenerateFindingRecommendationCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const b = rb(input, context); + const headers: any = {}; + b.bp("/recommendation/{id}"); + b.p("id", () => input.id!, "{id}", false); + const query: any = map({ + [_aA]: [, __expectNonNull(input[_aA]!, `analyzerArn`)], + }); + let body: any; + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}; + /** * serializeAws_restJson1GetAccessPreviewCommand */ @@ -452,6 +508,27 @@ export const se_GetFindingCommand = async ( return b.build(); }; +/** + * serializeAws_restJson1GetFindingRecommendationCommand + */ +export const se_GetFindingRecommendationCommand = async ( + input: GetFindingRecommendationCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const b = rb(input, context); + const headers: any = {}; + b.bp("/recommendation/{id}"); + b.p("id", () => input.id!, "{id}", false); + const query: any = map({ + [_aA]: [, __expectNonNull(input[_aA]!, `analyzerArn`)], + [_mR]: [() => input.maxResults !== void 0, () => input[_mR]!.toString()], + [_nT]: [, input[_nT]!], + }); + let body: any; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}; + /** * serializeAws_restJson1GetFindingV2Command */ @@ -945,6 +1022,29 @@ export const de_CheckNoNewAccessCommand = async ( return contents; }; +/** + * deserializeAws_restJson1CheckNoPublicAccessCommand + */ +export const de_CheckNoPublicAccessCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents: any = map({ + $metadata: deserializeMetadata(output), + }); + const data: Record = __expectNonNull(__expectObject(await parseBody(output.body, context)), "body"); + const doc = take(data, { + message: __expectString, + reasons: _json, + result: __expectString, + }); + Object.assign(contents, doc); + return contents; +}; + /** * deserializeAws_restJson1CreateAccessPreviewCommand */ @@ -1038,6 +1138,23 @@ export const de_DeleteArchiveRuleCommand = async ( return contents; }; +/** + * deserializeAws_restJson1GenerateFindingRecommendationCommand + */ +export const de_GenerateFindingRecommendationCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents: any = map({ + $metadata: deserializeMetadata(output), + }); + await collectBody(output.body, context); + return contents; +}; + /** * deserializeAws_restJson1GetAccessPreviewCommand */ @@ -1143,6 +1260,34 @@ export const de_GetFindingCommand = async ( return contents; }; +/** + * deserializeAws_restJson1GetFindingRecommendationCommand + */ +export const de_GetFindingRecommendationCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents: any = map({ + $metadata: deserializeMetadata(output), + }); + const data: Record = __expectNonNull(__expectObject(await parseBody(output.body, context)), "body"); + const doc = take(data, { + completedAt: (_) => __expectNonNull(__parseRfc3339DateTimeWithOffset(_)), + error: _json, + nextToken: __expectString, + recommendationType: __expectString, + recommendedSteps: (_) => de_RecommendedStepList(_, context), + resourceArn: __expectString, + startedAt: (_) => __expectNonNull(__parseRfc3339DateTimeWithOffset(_)), + status: __expectString, + }); + Object.assign(contents, doc); + return contents; +}; + /** * deserializeAws_restJson1GetFindingV2Command */ @@ -1843,6 +1988,8 @@ const se_CloudTrailDetails = (input: CloudTrailDetails, context: __SerdeContext) // se_RegionList omitted. +// se_ResourcesList omitted. + // se_S3AccessPointConfiguration omitted. // se_S3AccessPointConfigurationsMap omitted. @@ -2326,6 +2473,35 @@ const de_PolicyGenerationList = (output: any, context: __SerdeContext): PolicyGe // de_ReasonSummaryList omitted. +// de_RecommendationError omitted. + +/** + * deserializeAws_restJson1RecommendedStep + */ +const de_RecommendedStep = (output: any, context: __SerdeContext): RecommendedStep => { + if (output.unusedPermissionsRecommendedStep != null) { + return { + unusedPermissionsRecommendedStep: de_UnusedPermissionsRecommendedStep( + output.unusedPermissionsRecommendedStep, + context + ), + }; + } + return { $unknown: Object.entries(output)[0] }; +}; + +/** + * deserializeAws_restJson1RecommendedStepList + */ +const de_RecommendedStepList = (output: any, context: __SerdeContext): RecommendedStep[] => { + const retVal = (output || []) + .filter((e: any) => e != null) + .map((entry: any) => { + return de_RecommendedStep(__expectUnion(entry), context); + }); + return retVal; +}; + // de_RegionList omitted. // de_S3AccessPointConfiguration omitted. @@ -2425,6 +2601,21 @@ const de_UnusedPermissionDetails = (output: any, context: __SerdeContext): Unuse }) as any; }; +/** + * deserializeAws_restJson1UnusedPermissionsRecommendedStep + */ +const de_UnusedPermissionsRecommendedStep = ( + output: any, + context: __SerdeContext +): UnusedPermissionsRecommendedStep => { + return take(output, { + existingPolicyId: __expectString, + policyUpdatedAt: (_: any) => __expectNonNull(__parseRfc3339DateTimeWithOffset(_)), + recommendedAction: __expectString, + recommendedPolicy: __expectString, + }) as any; +}; + // de_ValidatePolicyFinding omitted. // de_ValidatePolicyFindingList omitted. diff --git a/codegen/sdk-codegen/aws-models/accessanalyzer.json b/codegen/sdk-codegen/aws-models/accessanalyzer.json index 178334f4a42b..57360988d1a4 100644 --- a/codegen/sdk-codegen/aws-models/accessanalyzer.json +++ b/codegen/sdk-codegen/aws-models/accessanalyzer.json @@ -7,16 +7,27 @@ "actions": { "target": "com.amazonaws.accessanalyzer#ActionsList", "traits": { + "smithy.api#addedDefault": {}, + "smithy.api#default": [], "smithy.api#documentation": "

A list of actions for the access permissions. Any strings that can be used as an action\n in an IAM policy can be used in the list of actions to check.

", "smithy.api#length": { "max": 100 - }, - "smithy.api#required": {} + } + } + }, + "resources": { + "target": "com.amazonaws.accessanalyzer#ResourcesList", + "traits": { + "smithy.api#default": [], + "smithy.api#documentation": "

A list of resources for the access permissions. Any strings that can be used as a\n resource in an IAM policy can be used in the list of resources to check.

", + "smithy.api#length": { + "max": 100 + } } } }, "traits": { - "smithy.api#documentation": "

Contains information about actions that define permissions to check against a\n policy.

" + "smithy.api#documentation": "

Contains information about actions and resources that define permissions to check\n against a policy.

" } }, "com.amazonaws.accessanalyzer#AccessAnalyzer": { @@ -35,9 +46,15 @@ { "target": "com.amazonaws.accessanalyzer#CheckNoNewAccess" }, + { + "target": "com.amazonaws.accessanalyzer#CheckNoPublicAccess" + }, { "target": "com.amazonaws.accessanalyzer#CreateAccessPreview" }, + { + "target": "com.amazonaws.accessanalyzer#GenerateFindingRecommendation" + }, { "target": "com.amazonaws.accessanalyzer#GetAccessPreview" }, @@ -47,6 +64,9 @@ { "target": "com.amazonaws.accessanalyzer#GetFinding" }, + { + "target": "com.amazonaws.accessanalyzer#GetFindingRecommendation" + }, { "target": "com.amazonaws.accessanalyzer#GetFindingV2" }, @@ -1156,6 +1176,85 @@ ] } }, + "com.amazonaws.accessanalyzer#AccessCheckResourceType": { + "type": "string", + "traits": { + "smithy.api#enum": [ + { + "value": "AWS::DynamoDB::Table", + "name": "DYNAMODB_TABLE" + }, + { + "value": "AWS::DynamoDB::Stream", + "name": "DYNAMODB_STREAM" + }, + { + "value": "AWS::EFS::FileSystem", + "name": "EFS_FILESYSTEM" + }, + { + "value": "AWS::OpenSearchService::Domain", + "name": "OPENSEARCHSERVICE_DOMAIN" + }, + { + "value": "AWS::Kinesis::Stream", + "name": "KINESIS_DATA_STREAM" + }, + { + "value": "AWS::Kinesis::StreamConsumer", + "name": "KINESIS_STREAM_CONSUMER" + }, + { + "value": "AWS::KMS::Key", + "name": "KMS_KEY" + }, + { + "value": "AWS::Lambda::Function", + "name": "LAMBDA_FUNCTION" + }, + { + "value": "AWS::S3::Bucket", + "name": "S3_BUCKET" + }, + { + "value": "AWS::S3::AccessPoint", + "name": "S3_ACCESS_POINT" + }, + { + "value": "AWS::S3Express::DirectoryBucket", + "name": "S3EXPRESS_DIRECTORYBUCKET" + }, + { + "value": "AWS::S3::Glacier", + "name": "S3_GLACIER" + }, + { + "value": "AWS::S3Outposts::Bucket", + "name": "S3_OUTPOSTS_BUCKET" + }, + { + "value": "AWS::S3Outposts::AccessPoint", + "name": "S3_OUTPOSTS_ACCESS_POINT" + }, + { + "value": "AWS::SecretsManager::Secret", + "name": "SECRETSMANAGER_SECRET" + }, + { + "value": "AWS::SNS::Topic", + "name": "SNS_TOPIC" + }, + { + "value": "AWS::SQS::Queue", + "name": "SQS_QUEUE" + }, + { + "value": "AWS::IAM::AssumeRolePolicyDocument", + "name": "ROLE_TRUST" + } + ] + } + }, "com.amazonaws.accessanalyzer#AccessDeniedException": { "type": "structure", "members": { @@ -2003,6 +2102,63 @@ ], "traits": { "smithy.api#documentation": "

Checks whether the specified access isn't allowed by a policy.

", + "smithy.api#examples": [ + { + "title": "Passing check. Restrictive identity policy.", + "input": { + "access": [ + { + "actions": ["s3:PutObject"] + } + ], + "policyDocument": "{\"Version\":\"2012-10-17\",\"Id\":\"123\",\"Statement\":[{\"Sid\":\"AllowJohnDoe\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:user/JohnDoe\"},\"Action\":\"s3:GetObject\",\"Resource\":\"*\"}]}", + "policyType": "RESOURCE_POLICY" + }, + "output": { + "result": "PASS", + "message": "The policy document does not grant access to perform the listed actions or resources." + } + }, + { + "title": "Passing check. Restrictive S3 Bucket resource policy.", + "input": { + "access": [ + { + "resources": ["arn:aws:s3:::sensitive-bucket/*"] + } + ], + "policyDocument": "{\"Version\":\"2012-10-17\",\"Id\":\"123\",\"Statement\":[{\"Sid\":\"AllowJohnDoe\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:user/JohnDoe\"},\"Action\":\"s3:PutObject\",\"Resource\":\"arn:aws:s3:::non-sensitive-bucket/*\"}]}", + "policyType": "RESOURCE_POLICY" + }, + "output": { + "result": "PASS", + "message": "The policy document does not grant access to perform the listed actions or resources." + } + }, + { + "title": "Failing check. Permissive S3 Bucket resource policy.", + "input": { + "access": [ + { + "resources": ["arn:aws:s3:::my-bucket/*"] + } + ], + "policyDocument": "{\"Version\":\"2012-10-17\",\"Id\":\"123\",\"Statement\":[{\"Sid\":\"AllowJohnDoe\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:user/JohnDoe\"},\"Action\":\"s3:PutObject\",\"Resource\":\"arn:aws:s3:::my-bucket/*\"}]}", + "policyType": "RESOURCE_POLICY" + }, + "output": { + "result": "FAIL", + "message": "The policy document grants access to perform one or more of the listed actions or resources.", + "reasons": [ + { + "description": "One or more of the listed actions or resources in the statement with sid: AllowJohnDoe.", + "statementIndex": 0, + "statementId": "AllowJohnDoe" + } + ] + } + } + ], "smithy.api#http": { "uri": "/policy/check-access-not-granted", "method": "POST", @@ -2025,7 +2181,7 @@ "access": { "target": "com.amazonaws.accessanalyzer#AccessList", "traits": { - "smithy.api#documentation": "

An access object containing the permissions that shouldn't be granted by the specified\n policy.

", + "smithy.api#documentation": "

An access object containing the permissions that shouldn't be granted by the specified\n policy. If only actions are specified, IAM Access Analyzer checks for access of the actions on\n all resources in the policy. If only resources are specified, then IAM Access Analyzer checks\n which actions have access to the specified resources. If both actions and resources are\n specified, then IAM Access Analyzer checks which of the specified actions have access to the\n specified resources.

", "smithy.api#length": { "max": 1 }, @@ -2194,6 +2350,139 @@ ] } }, + "com.amazonaws.accessanalyzer#CheckNoPublicAccess": { + "type": "operation", + "input": { + "target": "com.amazonaws.accessanalyzer#CheckNoPublicAccessRequest" + }, + "output": { + "target": "com.amazonaws.accessanalyzer#CheckNoPublicAccessResponse" + }, + "errors": [ + { + "target": "com.amazonaws.accessanalyzer#AccessDeniedException" + }, + { + "target": "com.amazonaws.accessanalyzer#InternalServerException" + }, + { + "target": "com.amazonaws.accessanalyzer#InvalidParameterException" + }, + { + "target": "com.amazonaws.accessanalyzer#ThrottlingException" + }, + { + "target": "com.amazonaws.accessanalyzer#UnprocessableEntityException" + }, + { + "target": "com.amazonaws.accessanalyzer#ValidationException" + } + ], + "traits": { + "smithy.api#documentation": "

Checks whether a resource policy can grant public access to the specified resource\n type.

", + "smithy.api#examples": [ + { + "title": "Passing check. S3 Bucket policy without public access.", + "input": { + "policyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"Bob\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::111122223333:user/JohnDoe\"},\"Action\":[\"s3:GetObject\"]}]}", + "resourceType": "AWS::S3::Bucket" + }, + "output": { + "result": "PASS", + "message": "The resource policy does not grant public access for the given resource type." + } + }, + { + "title": "Failing check. S3 Bucket policy with public access.", + "input": { + "policyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"Bob\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":[\"s3:GetObject\"]}]}", + "resourceType": "AWS::S3::Bucket" + }, + "output": { + "result": "FAIL", + "message": "The resource policy grants public access for the given resource type.", + "reasons": [ + { + "description": "Public access granted in the following statement with sid: Bob.", + "statementIndex": 0, + "statementId": "Bob" + } + ] + } + } + ], + "smithy.api#http": { + "uri": "/policy/check-no-public-access", + "method": "POST", + "code": 200 + }, + "smithy.api#readonly": {}, + "smithy.api#suppress": ["HttpMethodSemantics"] + } + }, + "com.amazonaws.accessanalyzer#CheckNoPublicAccessRequest": { + "type": "structure", + "members": { + "policyDocument": { + "target": "com.amazonaws.accessanalyzer#AccessCheckPolicyDocument", + "traits": { + "smithy.api#documentation": "

The JSON policy document to evaluate for public access.

", + "smithy.api#required": {} + } + }, + "resourceType": { + "target": "com.amazonaws.accessanalyzer#AccessCheckResourceType", + "traits": { + "smithy.api#documentation": "

The type of resource to evaluate for public access. For example, to check for public\n access to Amazon S3 buckets, you can choose AWS::S3::Bucket for the resource\n type.

\n

For resource types not supported as valid values, IAM Access Analyzer will return an\n error.

", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#input": {} + } + }, + "com.amazonaws.accessanalyzer#CheckNoPublicAccessResponse": { + "type": "structure", + "members": { + "result": { + "target": "com.amazonaws.accessanalyzer#CheckNoPublicAccessResult", + "traits": { + "smithy.api#documentation": "

The result of the check for public access to the specified resource type. If the result\n is PASS, the policy doesn't allow public access to the specified resource\n type. If the result is FAIL, the policy might allow public access to the\n specified resource type.

" + } + }, + "message": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "

The message indicating whether the specified policy allows public access to\n resources.

" + } + }, + "reasons": { + "target": "com.amazonaws.accessanalyzer#ReasonSummaryList", + "traits": { + "smithy.api#documentation": "

A list of reasons why the specified resource policy grants public access for the\n resource type.

" + } + } + }, + "traits": { + "smithy.api#output": {} + } + }, + "com.amazonaws.accessanalyzer#CheckNoPublicAccessResult": { + "type": "string", + "traits": { + "smithy.api#enum": [ + { + "value": "PASS", + "name": "PASS" + }, + { + "value": "FAIL", + "name": "FAIL" + } + ] + } + }, "com.amazonaws.accessanalyzer#CloudTrailArn": { "type": "string", "traits": { @@ -3474,6 +3763,90 @@ "target": "com.amazonaws.accessanalyzer#FindingSummaryV2" } }, + "com.amazonaws.accessanalyzer#GenerateFindingRecommendation": { + "type": "operation", + "input": { + "target": "com.amazonaws.accessanalyzer#GenerateFindingRecommendationRequest" + }, + "output": { + "target": "smithy.api#Unit" + }, + "errors": [ + { + "target": "com.amazonaws.accessanalyzer#AccessDeniedException" + }, + { + "target": "com.amazonaws.accessanalyzer#InternalServerException" + }, + { + "target": "com.amazonaws.accessanalyzer#ThrottlingException" + }, + { + "target": "com.amazonaws.accessanalyzer#ValidationException" + } + ], + "traits": { + "smithy.api#documentation": "

Creates a recommendation for an unused permissions finding.

", + "smithy.api#examples": [ + { + "title": "Successfully started generating finding recommendation", + "input": { + "analyzerArn": "arn:aws:access-analyzer:us-east-1:111122223333:analyzer/a", + "id": "finding-id" + }, + "output": {} + }, + { + "title": "Failed field validation for id value", + "input": { + "analyzerArn": "arn:aws:access-analyzer:us-east-1:111122223333:analyzer/a", + "id": "!" + }, + "error": { + "shapeId": "com.amazonaws.accessanalyzer#ValidationException", + "content": { + "reason": "fieldValidationFailed", + "message": "Invalid id." + } + }, + "allowConstraintErrors": true + } + ], + "smithy.api#http": { + "uri": "/recommendation/{id}", + "method": "POST", + "code": 200 + } + } + }, + "com.amazonaws.accessanalyzer#GenerateFindingRecommendationRequest": { + "type": "structure", + "members": { + "analyzerArn": { + "target": "com.amazonaws.accessanalyzer#AnalyzerArn", + "traits": { + "smithy.api#documentation": "

The ARN of\n the analyzer used to generate the finding recommendation.

", + "smithy.api#httpQuery": "analyzerArn", + "smithy.api#required": {} + } + }, + "id": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "

The unique ID for the finding recommendation.

", + "smithy.api#httpLabel": {}, + "smithy.api#length": { + "min": 1, + "max": 2048 + }, + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#input": {} + } + }, "com.amazonaws.accessanalyzer#GeneratedPolicy": { "type": "structure", "members": { @@ -3858,6 +4231,234 @@ "smithy.api#readonly": {} } }, + "com.amazonaws.accessanalyzer#GetFindingRecommendation": { + "type": "operation", + "input": { + "target": "com.amazonaws.accessanalyzer#GetFindingRecommendationRequest" + }, + "output": { + "target": "com.amazonaws.accessanalyzer#GetFindingRecommendationResponse" + }, + "errors": [ + { + "target": "com.amazonaws.accessanalyzer#AccessDeniedException" + }, + { + "target": "com.amazonaws.accessanalyzer#InternalServerException" + }, + { + "target": "com.amazonaws.accessanalyzer#ResourceNotFoundException" + }, + { + "target": "com.amazonaws.accessanalyzer#ThrottlingException" + }, + { + "target": "com.amazonaws.accessanalyzer#ValidationException" + } + ], + "traits": { + "smithy.api#documentation": "

Retrieves information about a finding recommendation for the specified analyzer.

", + "smithy.api#examples": [ + { + "title": "Successfully fetched finding recommendation", + "input": { + "analyzerArn": "arn:aws:access-analyzer:us-east-1:111122223333:analyzer/a", + "id": "finding-id", + "maxResults": 3, + "nextToken": "token" + }, + "output": { + "startedAt": "2000-01-01T00:00:00Z", + "completedAt": "2000-01-01T00:00:01Z", + "resourceArn": "arn:aws:iam::111122223333:role/test", + "recommendedSteps": [ + { + "unusedPermissionsRecommendedStep": { + "recommendedAction": "DETACH_POLICY", + "existingPolicyId": "policy-id" + } + }, + { + "unusedPermissionsRecommendedStep": { + "recommendedAction": "CREATE_POLICY", + "existingPolicyId": "policy-id", + "recommendedPolicy": "policy-content" + } + } + ], + "recommendationType": "UnusedPermissionRecommendation", + "status": "SUCCEEDED" + } + }, + { + "title": "In progress finding recommendation", + "input": { + "analyzerArn": "arn:aws:access-analyzer:us-east-1:111122223333:analyzer/a", + "id": "finding-id", + "maxResults": 3 + }, + "output": { + "startedAt": "2000-01-01T00:00:00Z", + "resourceArn": "arn:aws:iam::111122223333:role/test", + "recommendationType": "UnusedPermissionRecommendation", + "status": "IN_PROGRESS" + } + }, + { + "title": "Failed finding recommendation", + "input": { + "analyzerArn": "arn:aws:access-analyzer:us-east-1:111122223333:analyzer/a", + "id": "finding-id", + "maxResults": 3 + }, + "output": { + "startedAt": "2000-01-01T00:00:00Z", + "completedAt": "2000-01-01T00:00:01Z", + "error": { + "code": "SERVICE_ERROR", + "message": "Service error. Please try again." + }, + "resourceArn": "arn:aws:iam::111122223333:role/test", + "recommendationType": "UnusedPermissionRecommendation", + "status": "FAILED" + } + }, + { + "title": "Failed field validation for id value", + "input": { + "analyzerArn": "arn:aws:access-analyzer:us-east-1:111122223333:analyzer/a", + "id": "!" + }, + "error": { + "shapeId": "com.amazonaws.accessanalyzer#ValidationException", + "content": { + "reason": "fieldValidationFailed", + "message": "Invalid id." + } + }, + "allowConstraintErrors": true + } + ], + "smithy.api#http": { + "uri": "/recommendation/{id}", + "method": "GET", + "code": 200 + }, + "smithy.api#paginated": { + "items": "recommendedSteps", + "pageSize": "maxResults", + "inputToken": "nextToken", + "outputToken": "nextToken" + }, + "smithy.api#readonly": {} + } + }, + "com.amazonaws.accessanalyzer#GetFindingRecommendationRequest": { + "type": "structure", + "members": { + "analyzerArn": { + "target": "com.amazonaws.accessanalyzer#AnalyzerArn", + "traits": { + "smithy.api#documentation": "

The ARN of\n the analyzer used to generate the finding recommendation.

", + "smithy.api#httpQuery": "analyzerArn", + "smithy.api#required": {} + } + }, + "id": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "

The unique ID for the finding recommendation.

", + "smithy.api#httpLabel": {}, + "smithy.api#length": { + "min": 1, + "max": 2048 + }, + "smithy.api#required": {} + } + }, + "maxResults": { + "target": "smithy.api#Integer", + "traits": { + "smithy.api#documentation": "

The maximum number of results to return in the response.

", + "smithy.api#httpQuery": "maxResults", + "smithy.api#range": { + "min": 1, + "max": 1000 + } + } + }, + "nextToken": { + "target": "com.amazonaws.accessanalyzer#Token", + "traits": { + "smithy.api#documentation": "

A token used for pagination of results returned.

", + "smithy.api#httpQuery": "nextToken" + } + } + }, + "traits": { + "smithy.api#input": {} + } + }, + "com.amazonaws.accessanalyzer#GetFindingRecommendationResponse": { + "type": "structure", + "members": { + "startedAt": { + "target": "com.amazonaws.accessanalyzer#Timestamp", + "traits": { + "smithy.api#documentation": "

The time at which the retrieval of the finding recommendation was started.

", + "smithy.api#required": {} + } + }, + "completedAt": { + "target": "com.amazonaws.accessanalyzer#Timestamp", + "traits": { + "smithy.api#documentation": "

The time at which the retrieval of the finding recommendation was completed.

" + } + }, + "nextToken": { + "target": "com.amazonaws.accessanalyzer#Token", + "traits": { + "smithy.api#documentation": "

A token used for pagination of results returned.

" + } + }, + "error": { + "target": "com.amazonaws.accessanalyzer#RecommendationError", + "traits": { + "smithy.api#documentation": "

Detailed information about the reason that the retrieval of a recommendation for the\n finding failed.

" + } + }, + "resourceArn": { + "target": "com.amazonaws.accessanalyzer#ResourceArn", + "traits": { + "smithy.api#documentation": "

The ARN of the resource of the finding.

", + "smithy.api#required": {} + } + }, + "recommendedSteps": { + "target": "com.amazonaws.accessanalyzer#RecommendedStepList", + "traits": { + "smithy.api#documentation": "

A group of recommended steps for the finding.

" + } + }, + "recommendationType": { + "target": "com.amazonaws.accessanalyzer#RecommendationType", + "traits": { + "smithy.api#documentation": "

The type of recommendation for the finding.

", + "smithy.api#required": {} + } + }, + "status": { + "target": "com.amazonaws.accessanalyzer#Status", + "traits": { + "smithy.api#documentation": "

The status of the retrieval of the finding recommendation.

", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#output": {} + } + }, "com.amazonaws.accessanalyzer#GetFindingRequest": { "type": "structure", "members": { @@ -5781,12 +6382,88 @@ "target": "com.amazonaws.accessanalyzer#ReasonSummary" } }, + "com.amazonaws.accessanalyzer#RecommendationError": { + "type": "structure", + "members": { + "code": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "

The error code for a failed retrieval of a recommendation for a finding.

", + "smithy.api#required": {} + } + }, + "message": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "

The error message for a failed retrieval of a recommendation for a finding.

", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "

Contains information about the reason that the retrieval of a recommendation for a\n finding failed.

" + } + }, + "com.amazonaws.accessanalyzer#RecommendationType": { + "type": "string", + "traits": { + "smithy.api#enum": [ + { + "value": "UnusedPermissionRecommendation", + "name": "UNUSED_PERMISSION_RECOMMENDATION" + } + ] + } + }, + "com.amazonaws.accessanalyzer#RecommendedRemediationAction": { + "type": "string", + "traits": { + "smithy.api#enum": [ + { + "value": "CREATE_POLICY", + "name": "CREATE_POLICY" + }, + { + "value": "DETACH_POLICY", + "name": "DETACH_POLICY" + } + ] + } + }, + "com.amazonaws.accessanalyzer#RecommendedStep": { + "type": "union", + "members": { + "unusedPermissionsRecommendedStep": { + "target": "com.amazonaws.accessanalyzer#UnusedPermissionsRecommendedStep", + "traits": { + "smithy.api#documentation": "

A recommended step for an unused permissions finding.

" + } + } + }, + "traits": { + "smithy.api#documentation": "

Contains information about a recommended step for an unused access analyzer\n finding.

" + } + }, + "com.amazonaws.accessanalyzer#RecommendedStepList": { + "type": "list", + "member": { + "target": "com.amazonaws.accessanalyzer#RecommendedStep" + } + }, "com.amazonaws.accessanalyzer#RegionList": { "type": "list", "member": { "target": "smithy.api#String" } }, + "com.amazonaws.accessanalyzer#Resource": { + "type": "string", + "traits": { + "smithy.api#length": { + "max": 2048 + } + } + }, "com.amazonaws.accessanalyzer#ResourceArn": { "type": "string", "traits": { @@ -5894,6 +6571,12 @@ ] } }, + "com.amazonaws.accessanalyzer#ResourcesList": { + "type": "list", + "member": { + "target": "com.amazonaws.accessanalyzer#Resource" + } + }, "com.amazonaws.accessanalyzer#RetiringPrincipal": { "type": "string" }, @@ -6320,6 +7003,25 @@ "smithy.api#documentation": "

Starts a scan of the policies applied to the specified resource.

" } }, + "com.amazonaws.accessanalyzer#Status": { + "type": "string", + "traits": { + "smithy.api#enum": [ + { + "value": "SUCCEEDED", + "name": "SUCCEEDED" + }, + { + "value": "FAILED", + "name": "FAILED" + }, + { + "value": "IN_PROGRESS", + "name": "IN_PROGRESS" + } + ] + } + }, "com.amazonaws.accessanalyzer#StatusReason": { "type": "structure", "members": { @@ -6751,7 +7453,7 @@ "lastAccessed": { "target": "com.amazonaws.accessanalyzer#Timestamp", "traits": { - "smithy.api#documentation": "

The time at which the permission last accessed.

" + "smithy.api#documentation": "

The time at which the permission was last accessed.

" } } }, @@ -6759,6 +7461,39 @@ "smithy.api#documentation": "

Contains information about an unused access finding for a permission. IAM Access Analyzer\n charges for unused access analysis based on the number of IAM roles and users analyzed\n per month. For more details on pricing, see IAM Access Analyzer\n pricing.

" } }, + "com.amazonaws.accessanalyzer#UnusedPermissionsRecommendedStep": { + "type": "structure", + "members": { + "policyUpdatedAt": { + "target": "com.amazonaws.accessanalyzer#Timestamp", + "traits": { + "smithy.api#documentation": "

The time at which the existing policy for the unused permissions finding was last\n updated.

" + } + }, + "recommendedAction": { + "target": "com.amazonaws.accessanalyzer#RecommendedRemediationAction", + "traits": { + "smithy.api#documentation": "

A recommendation of whether to create or detach a policy for an unused permissions\n finding.

", + "smithy.api#required": {} + } + }, + "recommendedPolicy": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "

If the recommended action for the unused permissions finding is to replace the existing\n policy, the contents of the recommended policy to replace the policy specified in the\n existingPolicyId field.

" + } + }, + "existingPolicyId": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "

If the recommended action for the unused permissions finding is to detach a policy, the\n ID of an existing policy to be detached.

" + } + } + }, + "traits": { + "smithy.api#documentation": "

Contains information about the action to take for a policy in an unused permissions\n finding.

" + } + }, "com.amazonaws.accessanalyzer#UpdateArchiveRule": { "type": "operation", "input": { @@ -7186,6 +7921,10 @@ { "value": "other", "name": "OTHER" + }, + { + "value": "notSupported", + "name": "NOT_SUPPORTED" } ] }