Metadata-Version: 2.4
Name: aws-war-lens
Version: 0.1.7
Summary: AWS Well-Architected Review — automated assessment and PDF report generator
License: PROPRIETARY SOFTWARE LICENSE AGREEMENT
        
        Copyright (c) 2025 BluNorth Technologies Inc. All rights reserved.
        
        This Software License Agreement ("Agreement") governs the use of AWS WAR Lens
        and all associated source code, documentation, and files (collectively, the
        "Software"), which are the exclusive intellectual property of BluNorth
        Technologies Inc. ("Company").
        
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        
        1. OWNERSHIP
        
           The Software is proprietary to BluNorth Technologies Inc. and is protected
           by copyright law and international treaties. No title or ownership of the
           Software is transferred to any party under this Agreement.
        
        2. PERMITTED USE
        
           Subject to the terms of this Agreement, you are permitted to install and
           run the Software solely for the purpose of performing AWS Well-Architected
           Review assessments on cloud infrastructure that you own or are explicitly
           authorized to assess.
        
        3. RESTRICTIONS
        
           You may NOT, without the prior written consent of BluNorth Technologies Inc.:
        
           a) Copy, reproduce, or duplicate the Software or any portion thereof;
           b) Modify, adapt, translate, or create derivative works based on the Software;
           c) Reverse engineer, decompile, disassemble, or attempt to derive the source
              code from any distributed form of the Software;
           d) Sell, sublicense, rent, lease, transfer, or otherwise commercially exploit
              the Software;
           e) Remove or alter any proprietary notices, labels, or marks on the Software;
           f) Use the Software to build a competing product or service.
        
        4. INTELLECTUAL PROPERTY
        
           All rights, title, and interest in and to the Software, including all
           intellectual property rights, remain exclusively with BluNorth Technologies
           Inc. Any feedback, suggestions, or contributions you provide regarding the
           Software may be used by BluNorth Technologies Inc. without obligation or
           restriction.
        
        5. DISCLAIMER OF WARRANTIES
        
           THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
           IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
           FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. BLUNORTH TECHNOLOGIES
           INC. DOES NOT WARRANT THAT THE SOFTWARE WILL BE ERROR-FREE OR UNINTERRUPTED.
        
        6. LIMITATION OF LIABILITY
        
           IN NO EVENT SHALL BLUNORTH TECHNOLOGIES INC. BE LIABLE FOR ANY INDIRECT,
           INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
           LIMITED TO, LOSS OF DATA, REVENUE, OR PROFITS) ARISING OUT OF OR IN
           CONNECTION WITH THE USE OR INABILITY TO USE THE SOFTWARE, EVEN IF ADVISED OF
           THE POSSIBILITY OF SUCH DAMAGES.
        
        7. TERMINATION
        
           This Agreement is effective until terminated. BluNorth Technologies Inc. may
           terminate this Agreement immediately upon notice if you breach any of its
           terms. Upon termination, you must cease all use of the Software and destroy
           all copies in your possession.
        
        8. GOVERNING LAW
        
           This Agreement shall be governed by and construed in accordance with
           applicable law. Any disputes arising under this Agreement shall be subject
           to the exclusive jurisdiction of the courts competent to BluNorth
           Technologies Inc.'s place of business.
        
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        
        CONTACT
        
        For licensing inquiries, permissions, or commercial use requests:
        
          BluNorth Technologies Inc.
          https://www.blunorthtech.com/
License-File: LICENSE
Requires-Python: >=3.13
Requires-Dist: anthropic>=0.102.0
Requires-Dist: boto3>=1.34.96
Requires-Dist: jinja2>=3.1.6
Requires-Dist: python-dotenv>=1.2.1
Requires-Dist: weasyprint>=66.0
Description-Content-Type: text/markdown

# AWS WAR Lens

> Copyright (c) 2025 [BluNorth Technologies Inc.](https://www.blunorthtech.com/) All rights reserved. See [LICENSE](LICENSE) for terms.

Automated AWS Well-Architected Review assessments. Scans your AWS account across all six pillars, produces risk-rated findings, and generates a PDF report — with optional LLM-powered narrative and prioritization.

## Features

- **175 programmatic checks** across all 6 Well-Architected pillars
- **Risk-rated findings** — CRITICAL / HIGH / MEDIUM / LOW / PASS
- **PDF report** with executive summary, top priorities, and cross-finding correlations
- **Multi-region scanning** — `--region all` scans every opted-in region in parallel
- **No infrastructure required** — runs locally or in Docker against any AWS account

## Pillars

| Pillar | Checks |
|---|---|
| Security | 61 |
| Reliability | 44 |
| Operational Excellence | 34 |
| Performance Efficiency | 14 |
| Sustainability | 11 |
| Cost Optimization | 11 |

## Installation

```bash
pip install aws-war-lens
```

> **Note:** WeasyPrint (used for PDF generation) requires native system libraries on Linux/macOS. See [WeasyPrint installation docs](https://doc.courtbouillon.org/weasyprint/stable/first_steps.html) if you hit dependency errors.

## Usage

```bash
# Scan a single region (security pillar by default)
aws-war-lens --region eu-west-1

# Scan multiple pillars
aws-war-lens --region eu-west-1 --pillars security reliability cost_optimization

# Scan all opted-in regions
aws-war-lens --region all

# Skip LLM analysis (no ANTHROPIC_API_KEY needed)
aws-war-lens --region eu-west-1 --no-llm

# Use a named AWS profile
aws-war-lens --region eu-west-1 --profile myprofile

# Use explicit credentials
aws-war-lens --region eu-west-1 --access-key AKIA... --secret-key xxxx
```

The PDF report is saved to `output/` by default. Use `--output <dir>` to change it.

## Authentication

Credentials are resolved in this order:

1. `--access-key` / `--secret-key` / `--session-token` flags
2. `--profile` named profile from `~/.aws/credentials`
3. `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` environment variables
4. Default AWS CLI profile
5. IAM instance profile / ECS task role / Lambda execution role

## LLM Analysis

Set `ANTHROPIC_API_KEY` in your environment (or a `.env` file) to enable LLM-powered narrative, executive summary, and cross-finding correlation in the report. Without it, the report renders with raw findings only.

```bash
export ANTHROPIC_API_KEY=sk-ant-...
aws-war-lens --region eu-west-1
```

## Docker

```bash
docker run --rm \
  -e ANTHROPIC_API_KEY=sk-ant-... \
  -e AWS_ACCESS_KEY_ID=... \
  -e AWS_SECRET_ACCESS_KEY=... \
  -e AWS_SESSION_TOKEN=... \
  -v "$(pwd)/output:/app/output" \
  aws-war-lens --region eu-west-1
```

## Available Pillars

| Value | Description |
|---|---|
| `security` | IAM, S3, GuardDuty, CloudTrail, KMS, VPC, ACM, and more |
| `reliability` | Auto Scaling, RDS multi-AZ, backups, Route 53, quotas |
| `performance` | Instance families, Graviton, DynamoDB, CloudFront, ElastiCache |
| `cost_optimization` | Idle resources, rightsizing, reserved capacity, orphaned snapshots |
| `operational_excellence` | CloudWatch alarms, SSM, tagging, CI/CD, ECS configuration |
| `sustainability` | Graviton adoption, Fargate, auto-scaling, S3 intelligent tiering |

## IAM Permissions

**Option 1 — Recommended (least privilege):** Create a dedicated IAM policy using the JSON provided below and attach it to a new user or role.

**AWS Console:** IAM → Policies → Create policy → JSON tab → paste the policy below → name it `AWSScannerReadOnly`

**AWS CLI:**
```bash
aws iam create-policy \
  --policy-name AWSScannerReadOnly \
  --policy-document file://policy.json
```

**Option 2 — Use existing credentials:** If the credentials you already have (admin, power user, or an existing role) include at least the permissions listed below, you can use them directly without creating a new policy.

---

<details>
<summary>Copy IAM policy JSON</summary>

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "STSAuthentication",
      "Effect": "Allow",
      "Action": ["sts:GetCallerIdentity"],
      "Resource": "*"
    },
    {
      "Sid": "EC2ReadOnly",
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeRegions", "ec2:DescribeInstances", "ec2:DescribeSecurityGroups",
        "ec2:DescribeVolumes", "ec2:DescribeSnapshots", "ec2:DescribeImages",
        "ec2:DescribeAddresses", "ec2:GetEbsEncryptionByDefault", "ec2:DescribeVpcs",
        "ec2:DescribeSubnets", "ec2:DescribeNetworkAcls", "ec2:DescribeVpcEndpoints",
        "ec2:DescribeFlowLogs", "ec2:DescribeNatGateways", "ec2:DescribePlacementGroups"
      ],
      "Resource": "*"
    },
    {
      "Sid": "IAMReadOnly",
      "Effect": "Allow",
      "Action": [
        "iam:GetAccountSummary", "iam:GetAccountPasswordPolicy", "iam:GetCredentialReport",
        "iam:GenerateCredentialReport", "iam:GetRole", "iam:ListUsers",
        "iam:ListAttachedUserPolicies", "iam:ListUserPolicies", "iam:ListRoles",
        "iam:ListPolicies", "iam:GetPolicyVersion"
      ],
      "Resource": "*"
    },
    {
      "Sid": "S3ReadOnly",
      "Effect": "Allow",
      "Action": [
        "s3:ListAllMyBuckets", "s3:GetAccountPublicAccessBlock", "s3:GetPublicAccessBlock",
        "s3:GetBucketAcl", "s3:GetBucketPolicy", "s3:GetEncryptionConfiguration",
        "s3:GetBucketVersioning", "s3:GetBucketLogging", "s3:GetLifecycleConfiguration",
        "s3:GetReplicationConfiguration", "s3:GetBucketObjectLockConfiguration",
        "s3:GetBucketTagging", "s3:GetBucketAccelerateConfiguration",
        "s3:ListBucketIntelligentTieringConfigurations", "s3:ListBucket"
      ],
      "Resource": "*"
    },
    {
      "Sid": "RDSReadOnly",
      "Effect": "Allow",
      "Action": [
        "rds:DescribeDBInstances", "rds:DescribeDBSnapshots", "rds:DescribeDBClusters",
        "rds:DescribeReservedDBInstances", "rds:DescribeDBProxies"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ECSReadOnly",
      "Effect": "Allow",
      "Action": [
        "ecs:ListClusters", "ecs:DescribeClusters", "ecs:ListServices",
        "ecs:DescribeServices", "ecs:ListTaskDefinitionFamilies", "ecs:DescribeTaskDefinition"
      ],
      "Resource": "*"
    },
    {
      "Sid": "LambdaReadOnly",
      "Effect": "Allow",
      "Action": [
        "lambda:ListFunctions", "lambda:GetAccountSettings", "lambda:GetFunctionConcurrency",
        "lambda:GetFunctionEventInvokeConfig", "lambda:ListTags"
      ],
      "Resource": "*"
    },
    {
      "Sid": "SecretsManagerReadOnly",
      "Effect": "Allow",
      "Action": ["secretsmanager:ListSecrets", "secretsmanager:DescribeSecret"],
      "Resource": "*"
    },
    {
      "Sid": "KMSReadOnly",
      "Effect": "Allow",
      "Action": [
        "kms:ListKeys", "kms:DescribeKey", "kms:GetKeyRotationStatus", "kms:GetKeyPolicy"
      ],
      "Resource": "*"
    },
    {
      "Sid": "GuardDutyReadOnly",
      "Effect": "Allow",
      "Action": ["guardduty:ListDetectors", "guardduty:GetDetector", "guardduty:ListFindings"],
      "Resource": "*"
    },
    {
      "Sid": "SecurityHubReadOnly",
      "Effect": "Allow",
      "Action": ["securityhub:DescribeHub", "securityhub:ListStandardsSubscriptions"],
      "Resource": "*"
    },
    {
      "Sid": "ConfigReadOnly",
      "Effect": "Allow",
      "Action": [
        "config:DescribeConfigurationRecorders", "config:DescribeConfigurationRecorderStatus",
        "config:DescribeConfigRules"
      ],
      "Resource": "*"
    },
    {
      "Sid": "InspectorReadOnly",
      "Effect": "Allow",
      "Action": ["inspector2:BatchGetAccountStatus"],
      "Resource": "*"
    },
    {
      "Sid": "MacieReadOnly",
      "Effect": "Allow",
      "Action": ["macie2:GetMacieSession"],
      "Resource": "*"
    },
    {
      "Sid": "AccessAnalyzerReadOnly",
      "Effect": "Allow",
      "Action": ["access-analyzer:ListAnalyzers"],
      "Resource": "*"
    },
    {
      "Sid": "CloudTrailReadOnly",
      "Effect": "Allow",
      "Action": [
        "cloudtrail:DescribeTrails", "cloudtrail:GetTrailStatus", "cloudtrail:GetEventSelectors"
      ],
      "Resource": "*"
    },
    {
      "Sid": "CloudFrontReadOnly",
      "Effect": "Allow",
      "Action": ["cloudfront:ListDistributions", "cloudfront:GetDistribution"],
      "Resource": "*"
    },
    {
      "Sid": "ACMReadOnly",
      "Effect": "Allow",
      "Action": ["acm:ListCertificates", "acm:DescribeCertificate"],
      "Resource": "*"
    },
    {
      "Sid": "ELBReadOnly",
      "Effect": "Allow",
      "Action": [
        "elasticloadbalancing:DescribeLoadBalancers", "elasticloadbalancing:DescribeLoadBalancerAttributes",
        "elasticloadbalancing:DescribeTargetGroups", "elasticloadbalancing:DescribeTargetGroupAttributes",
        "elasticloadbalancing:DescribeTargetHealth"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AutoScalingReadOnly",
      "Effect": "Allow",
      "Action": [
        "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribePolicies",
        "autoscaling:DescribeScheduledActions"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ApplicationAutoScalingReadOnly",
      "Effect": "Allow",
      "Action": [
        "application-autoscaling:DescribeScalableTargets",
        "application-autoscaling:DescribeScalingPolicies"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ElastiCacheReadOnly",
      "Effect": "Allow",
      "Action": ["elasticache:DescribeReplicationGroups"],
      "Resource": "*"
    },
    {
      "Sid": "DynamoDBReadOnly",
      "Effect": "Allow",
      "Action": [
        "dynamodb:ListTables", "dynamodb:DescribeTable", "dynamodb:DescribeContinuousBackups"
      ],
      "Resource": "*"
    },
    {
      "Sid": "EFSReadOnly",
      "Effect": "Allow",
      "Action": ["elasticfilesystem:DescribeFileSystems", "elasticfilesystem:DescribeBackupPolicy"],
      "Resource": "*"
    },
    {
      "Sid": "SQSReadOnly",
      "Effect": "Allow",
      "Action": ["sqs:ListQueues", "sqs:GetQueueAttributes"],
      "Resource": "*"
    },
    {
      "Sid": "Route53ReadOnly",
      "Effect": "Allow",
      "Action": [
        "route53:ListHealthChecks", "route53:ListHostedZones", "route53:ListResourceRecordSets"
      ],
      "Resource": "*"
    },
    {
      "Sid": "BackupReadOnly",
      "Effect": "Allow",
      "Action": ["backup:ListBackupPlans"],
      "Resource": "*"
    },
    {
      "Sid": "ServiceQuotasReadOnly",
      "Effect": "Allow",
      "Action": ["servicequotas:GetServiceQuota"],
      "Resource": "*"
    },
    {
      "Sid": "ECRReadOnly",
      "Effect": "Allow",
      "Action": ["ecr:DescribeRepositories", "ecr:ListImages", "ecr:GetLifecyclePolicy"],
      "Resource": "*"
    },
    {
      "Sid": "CloudWatchReadOnly",
      "Effect": "Allow",
      "Action": ["cloudwatch:DescribeAlarms", "cloudwatch:ListDashboards"],
      "Resource": "*"
    },
    {
      "Sid": "CloudWatchLogsReadOnly",
      "Effect": "Allow",
      "Action": ["logs:DescribeLogGroups"],
      "Resource": "*"
    },
    {
      "Sid": "SSMReadOnly",
      "Effect": "Allow",
      "Action": [
        "ssm:DescribeInstanceInformation", "ssm:DescribeMaintenanceWindows",
        "ssm:ListAssociations", "ssm:DescribeParameters"
      ],
      "Resource": "*"
    },
    {
      "Sid": "SNSReadOnly",
      "Effect": "Allow",
      "Action": ["sns:ListTopics", "sns:GetTopicAttributes"],
      "Resource": "*"
    },
    {
      "Sid": "EventBridgeReadOnly",
      "Effect": "Allow",
      "Action": ["events:ListRules"],
      "Resource": "*"
    },
    {
      "Sid": "CloudFormationReadOnly",
      "Effect": "Allow",
      "Action": ["cloudformation:DescribeStacks"],
      "Resource": "*"
    },
    {
      "Sid": "SyntheticsReadOnly",
      "Effect": "Allow",
      "Action": ["synthetics:DescribeCanaries"],
      "Resource": "*"
    },
    {
      "Sid": "CostExplorerReadOnly",
      "Effect": "Allow",
      "Action": ["ce:ListCostAllocationTags"],
      "Resource": "*"
    },
    {
      "Sid": "SavingsPlansReadOnly",
      "Effect": "Allow",
      "Action": ["savingsplans:DescribeSavingsPlans"],
      "Resource": "*"
    }
  ]
}
```

</details>

Checks that lack permission are reported as **Scanner Coverage Gaps** in the PDF — they never fail silently.
