diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index ba5393d..45a3c51 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -11,7 +11,7 @@ This repository consolidates AWS DevOps Agent skills. Follow these conventions w ## Repository Structure ``` -sample-devops-agent-tools/ +tools-for-devops-agent/ ├── README.md # Project overview with skills table ├── .gitignore # Root-level ignores ├── skills/ @@ -126,7 +126,7 @@ Only these extensions are permitted inside skill directories (enforced by `skill 6. Test the skill with DevOps Agent before submitting. 7. Update the root `README.md` skills table with the new skill's name, agent types, author, and docs link. 8. Update the `llms.txt` file at the repo root — add the new skill to the "Available Skills" section following the existing format: `- [Skill Name](skills//SKILL.md): One-line description`. -9. If the skill requires IAM permissions beyond the `AIDevOpsAgentAccessPolicy` managed policy, add a new parameter, condition, and inline policy resource to `cloudformation/devops-agent-skill-policies.yaml`, and update the `SkillPolicySummary` output. +9. If the skill requires IAM permissions beyond the `AIDevOpsAgentAccessPolicy` managed policy, add a new parameter, condition, and inline policy resource to `cloudformation/devops-agent-skill-policies/devops-agent-skill-policies.yaml`, and update the `SkillPolicySummary` output. ## Zipping for Upload diff --git a/.kiro/steering/project-conventions.md b/.kiro/steering/project-conventions.md index ebf7373..c88b8ea 100644 --- a/.kiro/steering/project-conventions.md +++ b/.kiro/steering/project-conventions.md @@ -11,7 +11,7 @@ This repository consolidates AWS DevOps Agent skills. Follow these conventions w ## Repository Structure ``` -sample-devops-agent-tools/ +tools-for-devops-agent/ ├── README.md # Project overview with skills table ├── .gitignore # Root-level ignores ├── skills/ @@ -125,7 +125,7 @@ Only these extensions are permitted inside skill directories (enforced by `skill 6. Test the skill with DevOps Agent before submitting. 7. Update the root `README.md` skills table with the new skill's name, description, agent types, author, and docs link. 8. Update the `llms.txt` file at the repo root — add the new skill to the "Available Skills" section following the existing format: `- [Skill Name](skills//SKILL.md): One-line description`. -9. If the skill requires IAM permissions beyond the `AIDevOpsAgentAccessPolicy` managed policy, add a new parameter, condition, and inline policy resource to `cloudformation/devops-agent-skill-policies.yaml`, and update the `SkillPolicySummary` output. +9. If the skill requires IAM permissions beyond the `AIDevOpsAgentAccessPolicy` managed policy, add a new parameter, condition, and inline policy resource to `cloudformation/devops-agent-skill-policies/devops-agent-skill-policies.yaml`, and update the `SkillPolicySummary` output. ## Maintaining llms.txt diff --git a/README.md b/README.md index ef66d82..6c60f31 100644 --- a/README.md +++ b/README.md @@ -43,13 +43,13 @@ Most permissions are already covered by the AWS managed policy [`AIDevOpsAgentAc ```bash aws cloudformation deploy \ - --template-file cloudformation/devops-agent-skill-policies.yaml \ + --template-file cloudformation/devops-agent-skill-policies/devops-agent-skill-policies.yaml \ --stack-name devops-agent-skill-policies \ --parameter-overrides ExistingRoleName= \ --capabilities CAPABILITY_NAMED_IAM ``` -The template supports enabling/disabling policies per skill, optional region restrictions, and can either attach to an existing role or create a new one. See [`cloudformation/devops-agent-skill-policies.yaml`](cloudformation/devops-agent-skill-policies.yaml) for details. +The template supports enabling/disabling policies per skill, optional region restrictions, and can either attach to an existing role or create a new one. See [`cloudformation/devops-agent-skill-policies/devops-agent-skill-policies.yaml`](cloudformation/devops-agent-skill-policies/devops-agent-skill-policies.yaml) for details. ## Contributing diff --git a/cloudformation/devops-agent-alarm-investigations/README.md b/cloudformation/devops-agent-alarm-investigations/README.md new file mode 100644 index 0000000..9daaa5a --- /dev/null +++ b/cloudformation/devops-agent-alarm-investigations/README.md @@ -0,0 +1,165 @@ +# DevOps Agent alarm investigations + +Forwards **one** Amazon CloudWatch alarm to an AWS DevOps Agent generic webhook so that +alarm opens an investigation. + +**One stack = one alarm.** Deploy it again for each alarm you want forwarded. + +There is no AWS Lambda function and no code: an Amazon EventBridge rule matches the +alarm, an input transformer builds the webhook payload, and an EventBridge API +destination posts it with the webhook's API key. + +## Deployment sequence + +The webhook is created manually in the console (there is no `CreateWebhook` API), and +its API key is shown only once at creation — so it must exist **before** this stack. + +``` +1. Create the Agent Space (console / CLI / CloudFormation). +2. Console → Capabilities → Agent Space Webhook → Generate webhook. ← manual; no API + For "Webhook authentication type" choose API key. + Copy the webhook URL and the API key. The key is not retrievable later. +3. Deploy this stack with the webhook URL, the API key, and the alarm ARN. + Deploy once per alarm. +``` + +If you lose the key, rotate the webhook from the Capabilities tab. Rotation keeps the +same URL and issues a new key; update this stack with the new value afterwards. + +## What it creates + +| Resource | Purpose | +|----------|---------| +| Amazon EventBridge rule | Matches `CloudWatch Alarm State Change` events with `state.value = ALARM` **for the one configured alarm ARN** — the rule itself is the filter. Its input transformer builds the incident payload. | +| Amazon EventBridge connection | Holds the API key. EventBridge stores it in a Secrets Manager secret it creates and owns, and adds `Authorization: Bearer ` to every request. | +| Amazon EventBridge API destination | The webhook endpoint, invoked at a capped rate. | +| AWS IAM role | Lets the rule invoke that one API destination (`events:InvokeApiDestination`). Nothing else. | + +## How it works + +``` +CloudWatch alarm ──ALARM──▶ EventBridge rule (this alarm ARN only) + │ input transformer builds the incident JSON + ▼ + API destination + connection + │ POST, Authorization: Bearer + ▼ + DevOps Agent generic webhook ──▶ investigation +``` + +The payload the transformer produces: + +```json +{ + "eventType": "incident", + "incidentId": "", + "action": "created", + "priority": "HIGH", + "title": "CloudWatch alarm in ALARM state", + "description": "CloudWatch alarm entered ALARM state.", + "timestamp": "", + "data": { "metadata": { "alarmArn": "", "state": "ALARM" } } +} +``` + +Only the alarm ARN and the raised state are forwarded — no alarm name, reason, or metric +data. DevOps Agent enriches from the ARN. + +## Parameters + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `WebhookUrl` | *(required)* | HTTPS URL of the generic webhook. | +| `WebhookApiKey` | *(required)* | The API key (bearer token) from webhook creation. `NoEcho`, so it is masked in stack events, the console, and `describe-stacks`. | +| `AgentName` | *(required)* | Name/label of the target DevOps Agent. Used only to tag the taggable resources (`DevOpsAgent=`) for identification and cost allocation; it does not affect routing. | +| `AlarmArn` | *(required)* | ARN of the single CloudWatch alarm to forward. | +| `InvocationRateLimitPerSecond` | `1` | Cap on webhook invocations per second. Raise only if one stack must absorb a burst. | + +## Deploy + +```bash +aws cloudformation deploy \ + --template-file cloudformation/devops-agent-alarm-investigations/devops-agent-alarm-investigations.yaml \ + --stack-name devops-agent-alarm-investigations- \ + --capabilities CAPABILITY_IAM \ + --parameter-overrides \ + WebhookUrl="https://" \ + WebhookApiKey="" \ + AgentName="" \ + AlarmArn="arn:aws:cloudwatch:::alarm:" +``` + +## Cross-region and cross-account alarms + +Deploy this stack **once, in the same account and Region as the DevOps Agent**. Alarms in +*other* Regions or accounts reach it by **forwarding their state-change events** to the +agent Region's event bus; the rule matches on the alarm ARN, so a forwarded remote event +is handled exactly like a local one. Set `AlarmArn` to the alarm's real (possibly remote) +ARN. + +You create the forwarding rule in the alarm's own Region/account — ordinary EventBridge +bus-to-bus delivery: + +1. In the **alarm's Region/account**, create an EventBridge rule on the default bus + matching the alarm, targeting the **agent account/Region's default event bus**, with + an IAM role that grants `events:PutEvents` to that bus: + ```yaml + ForwardToAgentBus: + Type: AWS::Events::Rule + Properties: + EventPattern: + source: [aws.cloudwatch] + detail-type: [CloudWatch Alarm State Change] + detail: { state: { value: [ALARM] } } + Targets: + - Id: AgentBus + Arn: arn:aws:events:::event-bus/default + RoleArn: !GetAtt ForwardRole.Arn # role with events:PutEvents on that bus + ``` +2. **Cross-account only:** also add a resource policy on the agent bus + (`events:PutPermission`) allowing the source account to `PutEvents` — a bus accepts + events from another account only if its policy grants it. (Same-account, cross-Region + needs only the put-events role above.) + +The forwarded event lands on the agent Region's default bus still carrying +`resources: [""]`, so this stack's rule matches it. + +## Notes + +- **Region availability.** EventBridge API destinations to public HTTPS endpoints are not + available in every AWS Region. Check + [API destinations as targets](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-api-destinations.html#eb-api-destination-regions) + before deploying into a less common Region. +- **Deduplication.** `incidentId` is the EventBridge event id, which is constant across + retries, so redeliveries of the same event reuse the same `incidentId` and DevOps Agent + correlates them instead of opening duplicates. Repeat/flapping alarms are also + correlated natively; control flapping at the alarm's datapoints-to-alarm setting. +- **Delivery retries and stale events.** The retry policy allows up to 32 attempts over + 8 hours, and `MaximumEventAgeInSeconds` means EventBridge stops trying once an event is + older than that — so a long-delayed redelivery cannot open a stale investigation. +- **Endpoint timeout.** API destinations require the endpoint to respond within 5 seconds. + EventBridge retries timeouts within the retry policy above. +- **Monitoring delivery failures.** There is no function log group to read. The rule + publishes `InvocationAttempts`, `SuccessfulInvocationAttempts`, + `RetryInvocationAttempts` and `FailedInvocations` in the `AWS/Events` namespace, + dimensioned by `RuleName` — alarm on `FailedInvocations`, and watch + `RetryInvocationAttempts` for an endpoint that is struggling but still succeeding. Add + a dead-letter queue to the target if you need to inspect events that never landed. +- **Rotating the API key.** The connection resolves its key when the stack is created or + when the connection resource itself changes. After rotating the webhook, update the + stack with the new `WebhookApiKey` value; the key is not re-read automatically. +- **Keeping the key in your own secret.** If you already store the key in Secrets Manager, + replace the `ApiKeyValue` line in the template with a dynamic reference so the key never + passes through a stack parameter: + ```yaml + ApiKeyValue: '{{resolve:secretsmanager:MyWebhookSecret}}' + ``` + Substitute your secret's name (or full ARN for a cross-account secret), and drop the + `WebhookApiKey` parameter. The same rotation caveat applies: CloudFormation re-resolves + the reference only when the resource is updated. +- **API key versus HMAC.** The DevOps Agent generic webhook also supports HMAC + authentication, which adds payload integrity and replay protection. EventBridge + connections support only Basic, API key, and OAuth, and cannot compute a per-request + signature, so HMAC would require a signing Lambda between the rule and the webhook. + This template takes the API key path to stay code-free; over HTTPS to an AWS endpoint + the bearer token is the simpler trade. diff --git a/cloudformation/devops-agent-alarm-investigations/devops-agent-alarm-investigations.yaml b/cloudformation/devops-agent-alarm-investigations/devops-agent-alarm-investigations.yaml new file mode 100644 index 0000000..9eff842 --- /dev/null +++ b/cloudformation/devops-agent-alarm-investigations/devops-agent-alarm-investigations.yaml @@ -0,0 +1,220 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: > + Forwards a single Amazon CloudWatch alarm to an AWS DevOps Agent webhook so that + alarm opens an investigation. One stack = one alarm: it creates an Amazon + EventBridge rule scoped to that alarm's ARN, an EventBridge connection holding the + webhook API key, an EventBridge API destination pointing at the webhook, and a role + that lets the rule invoke it. No AWS Lambda function is involved. + + Prerequisite: create the Agent Space and its generic webhook with API key + authentication first (console — no API), then pass the webhook URL, the API key, + and the alarm ARN to this stack. + +Metadata: + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: AWS DevOps Agent Webhook + Parameters: + - WebhookUrl + - WebhookApiKey + - AgentName + - Label: + default: Alarm + Parameters: + - AlarmArn + - Label: + default: Delivery Tuning (optional) + Parameters: + - InvocationRateLimitPerSecond + ParameterLabels: + WebhookUrl: + default: DevOps Agent generic (API key) webhook URL + WebhookApiKey: + default: Webhook API key (bearer token) + AgentName: + default: Target DevOps Agent name (used to tag created resources) + AlarmArn: + default: ARN of the single CloudWatch alarm to forward + InvocationRateLimitPerSecond: + default: Max webhook invocations per second + +Parameters: + WebhookUrl: + Type: String + Description: > + HTTPS URL of the AWS DevOps Agent generic webhook, created in the Agent Space + console with API key authentication. + AllowedPattern: '^https://[A-Za-z0-9.-]+(:[0-9]+)?(/.*)?$' + ConstraintDescription: Must be an HTTPS URL. + + WebhookApiKey: + Type: String + NoEcho: true + Description: > + The API key (bearer token) shown once when you created the webhook. It is stored + in an AWS Secrets Manager secret that EventBridge creates and owns for the + connection. To keep the key in a secret you own instead, see the README. + MinLength: 1 + ConstraintDescription: Must not be empty. + + AgentName: + Type: String + Description: > + Name/label of the AWS DevOps Agent this integration targets. Used only to tag + the taggable resources this stack creates (EventBridge rule, IAM role) with + DevOpsAgent= for identification and cost allocation; it does not affect + routing (routing is determined by the webhook URL). + MinLength: 1 + MaxLength: 256 + AllowedPattern: "^[A-Za-z0-9 _.:/=+@-]{1,256}$" + ConstraintDescription: > + 1-256 characters using letters, numbers, spaces, and _ . : / = + - @ + (the AWS tag-value character set). + + AlarmArn: + Type: String + Description: > + ARN of the single Amazon CloudWatch alarm this stack forwards. Only ALARM + state changes for this exact alarm are sent to the webhook. + AllowedPattern: '^arn:aws[a-zA-Z-]*:cloudwatch:[a-z0-9-]+:[0-9]{12}:alarm:.+' + ConstraintDescription: Must be a CloudWatch alarm ARN. + + InvocationRateLimitPerSecond: + Type: Number + Default: 1 + MinValue: 1 + MaxValue: 300 + Description: > + (Optional) Maximum webhook invocations per second for the API destination. The + default of 1 suits a single low-frequency alarm. Raise it only if one stack must + absorb a burst; events above the limit are queued and retried inside the retry + window. + +Resources: + # Holds the bearer token. EventBridge stores it in a Secrets Manager secret it + # creates and owns for this connection, and adds the header on every invocation. + WebhookConnection: + Type: AWS::Events::Connection + Properties: + Description: !Sub 'API key for the AWS DevOps Agent webhook (${AgentName}).' + AuthorizationType: API_KEY + AuthParameters: + ApiKeyAuthParameters: + # The DevOps Agent webhook expects the token as a bearer token, so the + # header name is Authorization and the value carries the Bearer prefix. + ApiKeyName: Authorization + ApiKeyValue: !Sub 'Bearer ${WebhookApiKey}' + + WebhookApiDestination: + Type: AWS::Events::ApiDestination + Properties: + Description: !Sub 'AWS DevOps Agent webhook (${AgentName}).' + ConnectionArn: !GetAtt WebhookConnection.Arn + InvocationEndpoint: !Ref WebhookUrl + HttpMethod: POST + InvocationRateLimitPerSecond: !Ref InvocationRateLimitPerSecond + + # An API destination target requires a role granting events:InvokeApiDestination. + InvokeWebhookRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: events.amazonaws.com + Action: sts:AssumeRole + Condition: + StringEquals: + aws:SourceAccount: !Ref 'AWS::AccountId' + Policies: + - PolicyName: invoke-devops-agent-webhook + PolicyDocument: + Version: '2012-10-17' + Statement: + - Sid: InvokeWebhookApiDestination + Effect: Allow + Action: events:InvokeApiDestination + Resource: !GetAtt WebhookApiDestination.Arn + Tags: + - Key: ManagedBy + Value: CloudFormation + - Key: DevOpsAgent + Value: !Ref AgentName + + # Rule scoped to exactly one alarm ARN — the rule itself is the filter, so no + # code is needed to decide whether an event should be forwarded. + AlarmStateChangeRule: + Type: AWS::Events::Rule + Properties: + Description: !Sub 'Forwards ALARM-state changes for ${AlarmArn} to the DevOps Agent webhook.' + EventPattern: + source: + - aws.cloudwatch + detail-type: + - CloudWatch Alarm State Change + resources: + - !Ref AlarmArn + detail: + state: + value: + - ALARM + State: ENABLED + Targets: + - Id: DevOpsAgentWebhook + Arn: !GetAtt WebhookApiDestination.Arn + RoleArn: !GetAtt InvokeWebhookRole.Arn + HttpParameters: + HeaderParameters: + Content-Type: application/json + # incidentId is the EventBridge event id, which is constant across + # retries, so DevOps Agent deduplicates redeliveries of the same event + # instead of opening a new investigation for each attempt. + InputTransformer: + InputPathsMap: + eventId: $.id + eventTime: $.time + alarmArn: $.resources[0] + InputTemplate: | + { + "eventType": "incident", + "incidentId": "", + "action": "created", + "priority": "HIGH", + "title": "CloudWatch alarm in ALARM state", + "description": "CloudWatch alarm entered ALARM state.", + "timestamp": "", + "data": { + "metadata": { + "alarmArn": "", + "state": "ALARM" + } + } + } + RetryPolicy: + MaximumRetryAttempts: 32 + MaximumEventAgeInSeconds: 28800 + Tags: + - Key: ManagedBy + Value: CloudFormation + - Key: DevOpsAgent + Value: !Ref AgentName + +Outputs: + ApiDestinationArn: + Description: ARN of the API destination that posts to the webhook. + Value: !GetAtt WebhookApiDestination.Arn + + ConnectionArn: + Description: ARN of the EventBridge connection holding the webhook API key. + Value: !GetAtt WebhookConnection.Arn + + EventRuleArn: + Description: ARN of the EventBridge rule scoped to the alarm. + Value: !GetAtt AlarmStateChangeRule.Arn + + ForwardedAlarmArn: + Description: The CloudWatch alarm this stack forwards. + Value: !Ref AlarmArn diff --git a/cloudformation/devops-agent-skill-policies/README.md b/cloudformation/devops-agent-skill-policies/README.md new file mode 100644 index 0000000..e2bf20e --- /dev/null +++ b/cloudformation/devops-agent-skill-policies/README.md @@ -0,0 +1,115 @@ +# DevOps Agent skill IAM policies + +Adds the extra IAM permissions individual skills need to a DevOps Agent role, on top +of the AWS managed policy +[`AIDevOpsAgentAccessPolicy`](https://docs.aws.amazon.com/devopsagent/latest/userguide/aws-devops-agent-security-devops-agent-iam-permissions.html). + +Attach the policies to a role you already have, or let the template create one. This +template creates **no** infrastructure — only IAM. + +> This template does **not** create an Agent Space. Deploy the space separately and +> associate the role ARN from this stack's `DevOpsAgentRoleArn` output. + +## Role: existing or new + +| `ExistingRoleName` | Behaviour | +|--------------------|-----------| +| set to a role name | Attaches the inline policies to that existing role. | +| left empty (default) | Creates `DevOpsAgentRole-AgentSpace`, trusting `aidevops.amazonaws.com`, with `AIDevOpsAgentAccessPolicy` attached. | + +The trust policy on the created role is scoped with `aws:SourceAccount` and +`aws:SourceArn` (`arn:aws:aidevops:*::agentspace/*`) for confused-deputy +prevention. + +> **Multiple Agent Spaces:** the created role trusts all Agent Spaces in the account +> (`agentspace/*`), so one role can serve several spaces. Because the new-role name is +> fixed, the create-new path can only run once per account/Region. To give different +> spaces different permission sets, pre-create the roles and deploy this stack once per +> role with `ExistingRoleName`. + +## Parameters + +### Role configuration + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `ExistingRoleName` | `''` | Attach policies to this existing role. Empty creates `DevOpsAgentRole-AgentSpace`. | + +### Skill activation + +Each parameter is `'true'` / `'false'` and defaults to `'true'`. Set a skill to +`'false'` to leave out its policy. + +| Parameter | Skill | Permissions added | +|-----------|-------|-------------------| +| `EnableAwsHealthEvents` | `aws-health-events` | `health:DescribeEventTypes` | +| `EnableSupportCases` | `support-cases` | `support:DescribeCommunications` | +| `EnableRdsOperationReview` | `rds-operation-review` | `rds:DownloadDBLogFilePortion`, `logs:GetLogEvents` | +| `EnableInvestigationCostGuardrail` | `investigation-cost-guardrail` | `pricing:GetProducts` | +| `EnableMskOperations` | `msk-operations` | `kafka:GetBootstrapBrokers` | +| `EnableServiceQuotaCheck` | `service-quota-check` | Service Quotas read + `RequestServiceQuotaIncrease`, `CreateSupportCase`; `cloudwatch:GetMetricData`, `cloudwatch:GetMetricStatistics` | +| `EnableDmsOperationReview` | `database-migration-service-expertise` | `dms:TestConnection` | +| `EnableEksOperationReview` | `eks-operation-review` | None — already covered by the managed policy | +| `EnableEnrichWithSecurityAgent` | `enrich-with-aws-security-agent` | None — already covered by the managed policy | +| `EnableCrmInvestigationGuidelines` | `crm-production-investigation-guidelines` | None — already covered by the managed policy | +| `EnableSkipScheduledMaintenance` | `skip-scheduled-maintenance` | None — no IAM required | + +The last four parameters exist so the skill list stays complete and self-documenting; +toggling them changes nothing in the stack. + +`EnableAwsHealthEvents` and `EnableSupportCases` need an AWS Business or Enterprise +Support plan for the underlying APIs to return data. + +### Optional resource scoping + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `AllowedRegions` | `''` | Comma-delimited Region list. Empty means all Regions. When set, adds a `Deny` on every action outside those Regions, excepting the global services `health`, `support`, and `ce`. | + +## Always applied + +One policy is added regardless of the skill toggles: + +| Policy | Purpose | +|--------|---------| +| `AllowCreateResourceExplorerSLR` | `iam:CreateServiceLinkedRole` for `AWSServiceRoleForResourceExplorer`, required for topology discovery. | + +## Deploy + +Attach to an existing role: + +```bash +aws cloudformation deploy \ + --template-file cloudformation/devops-agent-skill-policies/devops-agent-skill-policies.yaml \ + --stack-name devops-agent-skill-policies \ + --parameter-overrides ExistingRoleName= \ + --capabilities CAPABILITY_NAMED_IAM +``` + +Create a new role instead, restricted to two Regions and without the Support-plan +skills: + +```bash +aws cloudformation deploy \ + --template-file cloudformation/devops-agent-skill-policies/devops-agent-skill-policies.yaml \ + --stack-name devops-agent-skill-policies \ + --capabilities CAPABILITY_NAMED_IAM \ + --parameter-overrides \ + AllowedRegions="us-east-1,eu-west-1" \ + EnableAwsHealthEvents=false \ + EnableSupportCases=false +``` + +## Outputs + +| Output | Description | +|--------|-------------| +| `DevOpsAgentRoleArn` | Role ARN to associate with your Agent Space. | +| `DevOpsAgentRoleName` | Role name. | +| `SkillPolicySummary` | Which skills got an inline policy, which are covered by the managed policy, and which need no IAM. | + +## Adding a skill + +When a new skill needs permissions beyond the managed policy, add a parameter, a +condition, and an `AWS::IAM::Policy` resource following the existing pattern, then +extend the `SkillPolicySummary` output. diff --git a/cloudformation/devops-agent-skill-policies.yaml b/cloudformation/devops-agent-skill-policies/devops-agent-skill-policies.yaml similarity index 100% rename from cloudformation/devops-agent-skill-policies.yaml rename to cloudformation/devops-agent-skill-policies/devops-agent-skill-policies.yaml diff --git a/skills/database-migration-service-expertise/README.md b/skills/database-migration-service-expertise/README.md index eb920c5..fb8d0c5 100644 --- a/skills/database-migration-service-expertise/README.md +++ b/skills/database-migration-service-expertise/README.md @@ -31,7 +31,7 @@ You need an existing [Agent Space](https://docs.aws.amazon.com/devopsagent/lates ### 2. IAM permissions for DMS read access -The Agent Space IAM role needs read-only permissions for DMS resources. Nearly all required actions are already covered by the `AIDevOpsAgentAccessPolicy` managed policy attached to the DevOps Agent role. The one exception is `dms:TestConnection`, which must be granted separately — use the [CloudFormation template](https://github.com/aws/tools-for-devops-agent/blob/main/cloudformation/devops-agent-skill-policies.yaml). +The Agent Space IAM role needs read-only permissions for DMS resources. Nearly all required actions are already covered by the `AIDevOpsAgentAccessPolicy` managed policy attached to the DevOps Agent role. The one exception is `dms:TestConnection`, which must be granted separately — use the [CloudFormation template](https://github.com/aws/tools-for-devops-agent/blob/main/cloudformation/devops-agent-skill-policies/devops-agent-skill-policies.yaml). For reference, the complete action set used by this skill: ```json diff --git a/skills/msk-operations/README.md b/skills/msk-operations/README.md index cf4686d..a9ff1b4 100644 --- a/skills/msk-operations/README.md +++ b/skills/msk-operations/README.md @@ -49,7 +49,7 @@ The AWS DevOps Agent's primary cloud-source role needs read access to MSK and CloudWatch. All calls except `kafka:GetBootstrapBrokers` are covered by `AIDevOpsAgentAccessPolicy`. `kafka:GetBootstrapBrokers` is granted by the opt-in `EnableMskOperations` parameter (default `true`) in -[`cloudformation/devops-agent-skill-policies.yaml`](https://github.com/aws/tools-for-devops-agent/blob/main/cloudformation/devops-agent-skill-policies.yaml). +[`cloudformation/devops-agent-skill-policies/devops-agent-skill-policies.yaml`](https://github.com/aws/tools-for-devops-agent/blob/main/cloudformation/devops-agent-skill-policies/devops-agent-skill-policies.yaml). The full set of actions the skill uses in practice: ```