diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a3807e5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +venv/ diff --git a/Pulumi.dev.yaml b/Pulumi.dev.yaml new file mode 100644 index 0000000..e8b1ec0 --- /dev/null +++ b/Pulumi.dev.yaml @@ -0,0 +1,4 @@ +environment: + - aws-oidc/aws-dev +config: + aws:region: us-west-2 diff --git a/Pulumi.yaml b/Pulumi.yaml new file mode 100644 index 0000000..c654351 --- /dev/null +++ b/Pulumi.yaml @@ -0,0 +1,11 @@ +name: cdk-converted +description: CDK to Pulumi migration - EC2 Dev environment +runtime: + name: python + options: + toolchain: pip + virtualenv: venv +config: + pulumi:tags: + value: + pulumi:template: aws-python diff --git a/README.md b/README.md index 8b13789..7b0b6d1 100644 --- a/README.md +++ b/README.md @@ -1 +1,92 @@ + # AWS Python S3 Bucket Pulumi Template + A minimal Pulumi template for provisioning a single AWS S3 bucket using Python. + + ## Overview + + This template provisions an S3 bucket (`pulumi_aws.s3.BucketV2`) in your AWS account and exports its ID as an output. It’s an ideal starting point when: + - You want to learn Pulumi with AWS in Python. + - You need a barebones S3 bucket deployment to build upon. + - You prefer a minimal template without extra dependencies. + + ## Prerequisites + + - An AWS account with permissions to create S3 buckets. + - AWS credentials configured in your environment (for example via AWS CLI or environment variables). + - Python 3.6 or later installed. + - Pulumi CLI already installed and logged in. + + ## Getting Started + + 1. Generate a new project from this template: + ```bash + pulumi new aws-python + ``` + 2. Follow the prompts to set your project name and AWS region (default: `us-east-1`). + 3. Change into your project directory: + ```bash + cd + ``` + 4. Preview the planned changes: + ```bash + pulumi preview + ``` + 5. Deploy the stack: + ```bash + pulumi up + ``` + 6. Tear down when finished: + ```bash + pulumi destroy + ``` + + ## Project Layout + + After running `pulumi new`, your directory will look like: + ``` + ├── __main__.py # Entry point of the Pulumi program + ├── Pulumi.yaml # Project metadata and template configuration + ├── requirements.txt # Python dependencies + └── Pulumi..yaml # Stack-specific configuration (e.g., Pulumi.dev.yaml) + ``` + + ## Configuration + + This template defines the following config value: + + - `aws:region` (string) + The AWS region to deploy resources into. + Default: `us-east-1` + + View or update configuration with: + ```bash + pulumi config get aws:region + pulumi config set aws:region us-west-2 + ``` + + ## Outputs + + Once deployed, the stack exports: + + - `bucket_name` — the ID of the created S3 bucket. + + Retrieve outputs with: + ```bash + pulumi stack output bucket_name + ``` + + ## Next Steps + + - Customize `__main__.py` to add or configure additional resources. + - Explore the Pulumi AWS SDK: https://www.pulumi.com/registry/packages/aws/ + - Break your infrastructure into modules for better organization. + - Integrate into CI/CD pipelines for automated deployments. + + ## Help and Community + + If you have questions or need assistance: + - Pulumi Documentation: https://www.pulumi.com/docs/ + - Community Slack: https://slack.pulumi.com/ + - GitHub Issues: https://github.com/pulumi/pulumi/issues + + Contributions and feedback are always welcome! \ No newline at end of file diff --git a/__main__.py b/__main__.py new file mode 100644 index 0000000..888349f --- /dev/null +++ b/__main__.py @@ -0,0 +1,295 @@ +"""CDK to Pulumi Migration - EC2 Dev Environment""" + +import pulumi +import pulumi_aws as aws + +# Get the current AWS region +current_region = aws.get_region() + +# VPC +vpc = aws.ec2.Vpc( + "VPC", + cidr_block="10.0.0.0/16", + enable_dns_hostnames=True, + enable_dns_support=True, + tags={ + "Name": "EC2-Dev/VPC/VPC", + }, + opts=pulumi.ResourceOptions(import_="vpc-0b47c4881fc5073e6"), +) + +# Internet Gateway +igw = aws.ec2.InternetGateway( + "VPCIGW", + vpc_id=vpc.id, + tags={ + "Name": "EC2-Dev/VPC/VPC", + }, + opts=pulumi.ResourceOptions(import_="igw-0a0eca7ea2e7fbc2f"), +) + +# Subnet 1 (us-west-2a) +subnet1 = aws.ec2.Subnet( + "VPCServerPublicSubnet1", + vpc_id=vpc.id, + cidr_block="10.0.0.0/24", + availability_zone="us-west-2a", + map_public_ip_on_launch=True, + tags={ + "Name": "EC2-Dev/VPC/VPC/ServerPublicSubnet1", + "aws-cdk:subnet-name": "ServerPublic", + "aws-cdk:subnet-type": "Public", + }, + opts=pulumi.ResourceOptions(import_="subnet-0fd1e04c5dbf71ac3"), +) + +# Subnet 2 (us-west-2b) +subnet2 = aws.ec2.Subnet( + "VPCServerPublicSubnet2", + vpc_id=vpc.id, + cidr_block="10.0.1.0/24", + availability_zone="us-west-2b", + map_public_ip_on_launch=True, + tags={ + "Name": "EC2-Dev/VPC/VPC/ServerPublicSubnet2", + "aws-cdk:subnet-name": "ServerPublic", + "aws-cdk:subnet-type": "Public", + }, + opts=pulumi.ResourceOptions(import_="subnet-05799c042f3b96581"), +) + +# Route Table 1 +route_table1 = aws.ec2.RouteTable( + "VPCServerPublicSubnet1RouteTable", + vpc_id=vpc.id, + tags={ + "Name": "EC2-Dev/VPC/VPC/ServerPublicSubnet1", + }, + opts=pulumi.ResourceOptions(import_="rtb-011077fa9f9097e90"), +) + +# Route Table 2 +route_table2 = aws.ec2.RouteTable( + "VPCServerPublicSubnet2RouteTable", + vpc_id=vpc.id, + tags={ + "Name": "EC2-Dev/VPC/VPC/ServerPublicSubnet2", + }, + opts=pulumi.ResourceOptions(import_="rtb-04689cc8810d74d71"), +) + +# Route Table Association 1 +route_table_assoc1 = aws.ec2.RouteTableAssociation( + "VPCServerPublicSubnet1RouteTableAssociation", + subnet_id=subnet1.id, + route_table_id=route_table1.id, + opts=pulumi.ResourceOptions( + import_="subnet-0fd1e04c5dbf71ac3/rtb-011077fa9f9097e90" + ), +) + +# Route Table Association 2 +route_table_assoc2 = aws.ec2.RouteTableAssociation( + "VPCServerPublicSubnet2RouteTableAssociation", + subnet_id=subnet2.id, + route_table_id=route_table2.id, + opts=pulumi.ResourceOptions( + import_="subnet-05799c042f3b96581/rtb-04689cc8810d74d71" + ), +) + +# Route 1 (Default route to IGW) +route1 = aws.ec2.Route( + "VPCServerPublicSubnet1DefaultRoute", + route_table_id=route_table1.id, + destination_cidr_block="0.0.0.0/0", + gateway_id=igw.id, + opts=pulumi.ResourceOptions(import_="rtb-011077fa9f9097e90_0.0.0.0/0"), +) + +# Route 2 (Default route to IGW) +route2 = aws.ec2.Route( + "VPCServerPublicSubnet2DefaultRoute", + route_table_id=route_table2.id, + destination_cidr_block="0.0.0.0/0", + gateway_id=igw.id, + opts=pulumi.ResourceOptions(import_="rtb-04689cc8810d74d71_0.0.0.0/0"), +) + +# SSH Security Group +ssh_security_group = aws.ec2.SecurityGroup( + "VPCSSHSecurityGroup", + vpc_id=vpc.id, + description="Security Group for SSH", + ingress=[ + aws.ec2.SecurityGroupIngressArgs( + protocol="tcp", + from_port=22, + to_port=22, + cidr_blocks=["0.0.0.0/0"], + description="from 0.0.0.0/0:22", + ) + ], + egress=[ + aws.ec2.SecurityGroupEgressArgs( + protocol="-1", + from_port=0, + to_port=0, + cidr_blocks=["0.0.0.0/0"], + description="Allow all outbound traffic by default", + ) + ], + opts=pulumi.ResourceOptions(import_="sg-041fd5ffe3dff1cbd"), +) + +# EC2 Instance Security Group +ec2_security_group = aws.ec2.SecurityGroup( + "EC2ec2InstanceSecurityGroup", + vpc_id=vpc.id, + description="EC2-Dev/EC2/ec2InstanceSecurityGroup", + egress=[ + aws.ec2.SecurityGroupEgressArgs( + protocol="-1", + from_port=0, + to_port=0, + cidr_blocks=["0.0.0.0/0"], + description="Allow all outbound traffic by default", + ) + ], + opts=pulumi.ResourceOptions(import_="sg-011ab470a7eb4234f"), +) + +# S3 Bucket for assets +asset_bucket = aws.s3.Bucket( + "EC2assetBucket", + bucket="ec2-dev-ec2assetbucketc584b4ab-0v8rysgr8ray", + tags={ + "aws-cdk:auto-delete-objects": "true", + "aws-cdk:cr-owned:6bed3ded": "true", + }, + opts=pulumi.ResourceOptions(import_="ec2-dev-ec2assetbucketc584b4ab-0v8rysgr8ray"), +) + +# S3 Bucket Public Access Block +bucket_public_access_block = aws.s3.BucketPublicAccessBlock( + "EC2assetBucketPublicAccessBlock", + bucket=asset_bucket.id, + block_public_acls=True, + block_public_policy=True, + ignore_public_acls=True, + restrict_public_buckets=True, + opts=pulumi.ResourceOptions(import_="ec2-dev-ec2assetbucketc584b4ab-0v8rysgr8ray"), +) + +# S3 Bucket Ownership Controls +bucket_ownership_controls = aws.s3.BucketOwnershipControls( + "EC2assetBucketOwnershipControls", + bucket=asset_bucket.id, + rule=aws.s3.BucketOwnershipControlsRuleArgs( + object_ownership="BucketOwnerPreferred", + ), + opts=pulumi.ResourceOptions(import_="ec2-dev-ec2assetbucketc584b4ab-0v8rysgr8ray"), +) + +# IAM Role for EC2 +ec2_role = aws.iam.Role( + "EC2serverEc2Role", + assume_role_policy="""{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +}""", + managed_policy_arns=[ + "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore", + "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy", + ], + inline_policies=[ + aws.iam.RoleInlinePolicyArgs( + name="EC2serverEc2RoleDefaultPolicy34EE5F1D", + policy="""{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", + "s3:Abort*" + ], + "Resource": [ + "arn:aws:s3:::ec2-dev-ec2assetbucketc584b4ab-0v8rysgr8ray", + "arn:aws:s3:::ec2-dev-ec2assetbucketc584b4ab-0v8rysgr8ray/*" + ] + } + ] +}""", + ), + aws.iam.RoleInlinePolicyArgs( + name="RetentionPolicy", + policy="""{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "logs:PutRetentionPolicy", + "Resource": "*" + } + ] +}""", + ), + ], + opts=pulumi.ResourceOptions( + import_="EC2-Dev-EC2serverEc2Role6775A3D4-6kxV4lkZWke6" + ), +) + +# IAM Instance Profile +instance_profile = aws.iam.InstanceProfile( + "EC2InstanceInstanceProfile", + role=ec2_role.name, + opts=pulumi.ResourceOptions( + import_="EC2-Dev-EC2InstanceInstanceProfile2CAA3051-xvtZubzupJkt" + ), +) + +# EC2 Instance +instance = aws.ec2.Instance( + "EC2Instance", + ami="ami-0a9e99f8d214ea170", + instance_type="m7g.large", + subnet_id=subnet1.id, + vpc_security_group_ids=[ec2_security_group.id, ssh_security_group.id], + iam_instance_profile=instance_profile.name, + user_data="#!/bin/bash", + metadata_options=aws.ec2.InstanceMetadataOptionsArgs( + http_tokens="required", + http_put_response_hop_limit=2, + ), + tags={ + "Name": "EC2-Dev/EC2/Instance", + }, + opts=pulumi.ResourceOptions(import_="i-070ed858d9b16833a"), +) + +# Exports +pulumi.export( + "ssm_command", pulumi.Output.concat("aws ssm start-session --target ", instance.id) +) +pulumi.export("ssh_command", pulumi.Output.concat("ssh ec2-user@", instance.public_dns)) +pulumi.export("instance_id", instance.id) +pulumi.export("vpc_id", vpc.id) +pulumi.export("bucket_name", asset_bucket.id) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..9a1b8d0 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pulumi>=3.0.0,<4.0.0 +pulumi-aws>=7.0.0,<8.0.0