CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pulumi--aws

A Pulumi package for creating and managing Amazon Web Services (AWS) cloud resources with infrastructure-as-code.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

security.mddocs/guides/

Security Best Practices

Comprehensive guide for implementing AWS security best practices with Pulumi.

Identity and Access Management

Principle of Least Privilege

Always grant the minimum permissions necessary.

const lambdaRole = new aws.iam.Role("lambda-role", {
    assumeRolePolicy: JSON.stringify({
        Version: "2012-10-17",
        Statement: [{
            Action: "sts:AssumeRole",
            Effect: "Allow",
            Principal: { Service: "lambda.amazonaws.com" },
        }],
    }),
});

// Specific permissions only
new aws.iam.RolePolicy("lambda-policy", {
    role: lambdaRole.id,
    policy: JSON.stringify({
        Version: "2012-10-17",
        Statement: [{
            Effect: "Allow",
            Action: ["dynamodb:GetItem", "dynamodb:PutItem"],
            Resource: table.arn,
        }],
    }),
});

Data Encryption

Encryption at Rest

// S3 bucket with encryption
const bucket = new aws.s3.Bucket("secure-bucket", {
    bucket: "secure-data-bucket",
    serverSideEncryptionConfiguration: {
        rule: {
            applyServerSideEncryptionByDefault: {
                sseAlgorithm: "aws:kms",
                kmsMasterKeyId: kmsKey.id,
            },
            bucketKeyEnabled: true,
        },
    },
});

// RDS with encryption
const db = new aws.rds.Instance("secure-db", {
    instanceClass: "db.t3.micro",
    allocatedStorage: 20,
    engine: "postgres",
    storageEncrypted: true,
    kmsKeyId: kmsKey.arn,
});

// EBS volume with encryption
const volume = new aws.ebs.Volume("secure-volume", {
    availabilityZone: "us-west-2a",
    size: 100,
    encrypted: true,
    kmsKeyId: kmsKey.id,
});

Encryption in Transit

// ALB with HTTPS only
const alb = new aws.lb.LoadBalancer("secure-alb", {
    loadBalancerType: "application",
    subnets: subnetIds,
});

const listener = new aws.lb.Listener("https", {
    loadBalancerArn: alb.arn,
    port: 443,
    protocol: "HTTPS",
    certificateArn: certificate.arn,
    defaultActions: [{
        type: "forward",
        targetGroupArn: targetGroup.arn,
    }],
});

// Redirect HTTP to HTTPS
const httpListener = new aws.lb.Listener("http-redirect", {
    loadBalancerArn: alb.arn,
    port: 80,
    protocol: "HTTP",
    defaultActions: [{
        type: "redirect",
        redirect: {
            port: "443",
            protocol: "HTTPS",
            statusCode: "HTTP_301",
        },
    }],
});

Network Security

VPC Isolation

const vpc = new aws.ec2.Vpc("secure-vpc", {
    cidrBlock: "10.0.0.0/16",
    enableDnsHostnames: true,
    enableDnsSupport: true,
    tags: { Name: "secure-vpc" },
});

// Private subnets for resources
const privateSubnet = new aws.ec2.Subnet("private", {
    vpcId: vpc.id,
    cidrBlock: "10.0.1.0/24",
    availabilityZone: "us-west-2a",
    mapPublicIpOnLaunch: false,
});

// Public subnets only for load balancers
const publicSubnet = new aws.ec2.Subnet("public", {
    vpcId: vpc.id,
    cidrBlock: "10.0.101.0/24",
    availabilityZone: "us-west-2a",
    mapPublicIpOnLaunch: true,
});

Security Groups

// Restrictive security group
const appSg = new aws.ec2.SecurityGroup("app-sg", {
    vpcId: vpc.id,
    description: "Application security group",
    ingress: [{
        protocol: "tcp",
        fromPort: 443,
        toPort: 443,
        cidrBlocks: ["10.0.0.0/16"], // Only from VPC
    }],
    egress: [{
        protocol: "-1",
        fromPort: 0,
        toPort: 0,
        cidrBlocks: ["0.0.0.0/0"],
    }],
});

Network ACLs

const nacl = new aws.ec2.NetworkAcl("private-nacl", {
    vpcId: vpc.id,
    ingress: [{
        protocol: "tcp",
        ruleNo: 100,
        action: "allow",
        cidrBlock: "10.0.0.0/16",
        fromPort: 443,
        toPort: 443,
    }],
    egress: [{
        protocol: "-1",
        ruleNo: 100,
        action: "allow",
        cidrBlock: "0.0.0.0/0",
        fromPort: 0,
        toPort: 0,
    }],
});

Secrets Management

AWS Secrets Manager

const dbSecret = new aws.secretsmanager.Secret("db-secret", {
    name: "database-credentials",
    description: "Database credentials",
});

const secretVersion = new aws.secretsmanager.SecretVersion("db-secret-version", {
    secretId: dbSecret.id,
    secretString: pulumi.jsonStringify({
        username: "admin",
        password: dbPassword, // From Pulumi config
    }),
});

// Automatic rotation
const rotationLambda = new aws.lambda.Function("rotation", {
    code: new pulumi.asset.AssetArchive({
        ".": new pulumi.asset.FileArchive("./rotation-lambda"),
    }),
    handler: "index.handler",
    runtime: "python3.11",
    role: rotationRole.arn,
});

new aws.secretsmanager.SecretRotation("rotation", {
    secretId: dbSecret.id,
    rotationLambdaArn: rotationLambda.arn,
    rotationRules: {
        automaticallyAfterDays: 30,
    },
});

Logging and Monitoring

Enable CloudTrail

const trailBucket = new aws.s3.Bucket("cloudtrail-logs", {
    bucket: "org-cloudtrail-logs",
    versioning: { enabled: true },
});

const trail = new aws.cloudtrail.Trail("audit", {
    s3BucketName: trailBucket.id,
    includeGlobalServiceEvents: true,
    isMultiRegionTrail: true,
    enableLogFileValidation: true,
    eventSelectors: [{
        readWriteType: "All",
        includeManagementEvents: true,
    }],
});

VPC Flow Logs

const flowLogRole = new aws.iam.Role("flow-log-role", {
    assumeRolePolicy: JSON.stringify({
        Version: "2012-10-17",
        Statement: [{
            Action: "sts:AssumeRole",
            Effect: "Allow",
            Principal: { Service: "vpc-flow-logs.amazonaws.com" },
        }],
    }),
});

const logGroup = new aws.cloudwatch.LogGroup("vpc-flow-logs", {
    retentionInDays: 90,
});

const flowLog = new aws.ec2.FlowLog("vpc-flow", {
    vpcId: vpc.id,
    trafficType: "ALL",
    logDestinationType: "cloud-watch-logs",
    logDestination: logGroup.arn,
    iamRoleArn: flowLogRole.arn,
});

GuardDuty

const detector = new aws.guardduty.Detector("main", {
    enable: true,
    findingPublishingFrequency: "FIFTEEN_MINUTES",
});

// Send findings to SNS
const findingsTopic = new aws.sns.Topic("guardduty-findings");

new aws.cloudwatch.EventRule("guardduty-findings", {
    eventPattern: JSON.stringify({
        source: ["aws.guardduty"],
        detailType: ["GuardDuty Finding"],
    }),
});

Compliance and Governance

Config Rules

const configRecorder = new aws.cfg.Recorder("recorder", {
    roleArn: configRole.arn,
    recordingGroup: {
        allSupported: true,
        includeGlobalResourceTypes: true,
    },
});

// Check for encrypted volumes
const encryptedVolumesRule = new aws.cfg.Rule("encrypted-volumes", {
    source: {
        owner: "AWS",
        sourceIdentifier: "ENCRYPTED_VOLUMES",
    },
});

Resource Tagging

// Enforce tagging strategy
const resourceTags = {
    Environment: "production",
    Project: "my-app",
    CostCenter: "engineering",
    ManagedBy: "pulumi",
};

const bucket = new aws.s3.Bucket("tagged-bucket", {
    tags: resourceTags,
});

Best Practices Checklist

  • ✅ Enable MFA for root and privileged accounts
  • ✅ Use IAM roles instead of long-term credentials
  • ✅ Encrypt data at rest and in transit
  • ✅ Use VPC for network isolation
  • ✅ Implement least privilege access
  • ✅ Enable CloudTrail in all regions
  • ✅ Use Secrets Manager for credentials
  • ✅ Enable GuardDuty for threat detection
  • ✅ Regular security audits with Config
  • ✅ Implement proper tagging strategy

Related Documentation

  • IAM Guide
  • Multi-Account Setup
  • Security Services

Install with Tessl CLI

npx tessl i tessl/npm-pulumi--aws

docs

index.md

quickstart.md

README.md

tile.json