// Module included in the following assemblies:
//
// * rosa_hcp/rosa-hcp-creating-cluster-with-aws-kms-key.adoc
// * rosa_hcp/rosa-hcp-egress-zero-install.adoc
// * rosa_hcp/rosa-hcp-quickstart-guide.adoc
// * rosa_hcp/rosa-hcp-sts-creating-a-cluster-quickly.adoc

ifeval::["{context}" == "rosa-hcp-egress-zero-install"]
:rosa-egress-lockdown:
endif::[]
:_mod-docs-content-type: PROCEDURE
[id="rosa-hcp-create-network_{context}"]
= Creating an AWS VPC using the ROSA CLI

The `rosa create network` command is available in v.1.2.48 or later of the {rosa-cli}. The command uses AWS CloudFormation to create a VPC and associated networking components necessary to install a {product-title} cluster. CloudFormation is a native AWS infrastructure-as-code tool and is compatible with the AWS CLI.

If you do not specify a template, CloudFormation uses a default template that creates resources with the following parameters:

[cols="2a,3a",options="header"]
|===
|VPC parameter
|Value

| Availability zones
| 1

| Region
| `us-east-1`

| VPC CIDR
| `10.0.0.0/16`
|===

You can create and customize CloudFormation templates to use with the `rosa create network` command. See the additional resources of this section for information on the default VPC template.

.Prerequisites

* You have configured your AWS account
* You have configured your Red Hat accounts
* You have installed the {rosa-cli} and configured it to the latest version

.Procedure

ifndef::rosa-egress-lockdown[]
. Create an AWS VPC using the default CloudFormations template by running the following command:
+
[source,terminal]
----
$ rosa create network
----

. Optional: Customize your VPC by specifying additional parameters.
+
You can use the `--param` flag to specify changes to the default VPC template. The following example command specifies custom values for `region`, `Name`, `AvailabilityZoneCount` and `VpcCidr`.
+
[source,terminal]
----
$ rosa create network --param Region=us-east-2 --param Name=quickstart-stack --param AvailabilityZoneCount=3 --param VpcCidr=10.0.0.0/16
----
+
The command takes about 5 minutes to run and provides regular status updates from AWS as resources are created. If there is an issue with CloudFormation, a rollback is attempted. For all other errors that are encountered, please follow the error message instructions or contact AWS support.
endif::rosa-egress-lockdown[]
// ifdef::rosa-egress-lockdown[]
// . Create a new directory for your CloudFormation templates by running the following command:
// +
// [source,terminal]
// ----
// $ mkdir TEMPLATES
// ----

// . Run the following command to create a local copy of this CloudFormation template to create a private VPC:
// +
// [source,terminal]
// ----
// $ cat<<-EOF>TEMPLATES/rosa-zero-egress-vpc.yaml
// AWSTemplateFormatVersion: '2010-09-09'
// Description: |
//   CloudFormation template for a Zero-Egress VPC for ROSA,
//   equivalent to the provided Terraform configuration.
//   This VPC includes private subnets, a security group for internal traffic,
//   and VPC Endpoints for STS, ECR (API, DKR), and S3 to facilitate
//   communication for ROSA in a private environment.

// Parameters:
//   ClusterName:
//     Type: String
//     Description: The name of the ROSA cluster, used for naming resources.

//   VpcCidrBlock:
//     Type: String
//     Default: 10.0.0.0/16
//     Description: CIDR block for the VPC.

//   PrivateSubnet1CidrBlock:
//     Type: String
//     Default: 10.0.1.0/24
//     Description: CIDR block for the first private subnet.

//   PrivateSubnet2CidrBlock:
//     Type: String
//     Default: 10.0.2.0/24
//     Description: CIDR block for the second private subnet.

//   AvailabilityZone1:
//     Type: AWS::EC2::AvailabilityZone::Name
//     Description: First Availability Zone for the private subnet.

//   AvailabilityZone2:
//     Type: AWS::EC2::AvailabilityZone::Name
//     Description: Second Availability Zone for the private subnet.

// Resources:
//   RosaVPC:
//     Type: AWS::EC2::VPC
//     Properties:
//       CidrBlock: !Ref VpcCidrBlock
//       EnableDnsSupport: true
//       EnableDnsHostnames: true
//       Tags:
//         - Key: Name
//           Value: !Sub ${ClusterName}-vpc
//         - Key: Terraform
//           Value: "true"
//         - Key: service
//           Value: ROSA
//         - Key: cluster_name
//           Value: !Ref ClusterName

//   PrivateSubnet1:
//     Type: AWS::EC2::Subnet
//     Properties:
//       VpcId: !Ref RosaVPC
//       CidrBlock: !Ref PrivateSubnet1CidrBlock
//       AvailabilityZone: !Ref AvailabilityZone1
//       MapPublicIpOnLaunch: false # Ensures it's private
//       Tags:
//         - Key: Name
//           Value: !Sub ${ClusterName}-private-subnet-1
//         - Key: Terraform
//           Value: "true"
//         - Key: service
//           Value: ROSA
//         - Key: cluster_name
//           Value: !Ref ClusterName
//         - Key: kubernetes.io/role/internal-elb
//           Value: "1" # Tag from Terraform

//   PrivateSubnet2:
//     Type: AWS::EC2::Subnet
//     Properties:
//       VpcId: !Ref RosaVPC
//       CidrBlock: !Ref PrivateSubnet2CidrBlock
//       AvailabilityZone: !Ref AvailabilityZone2
//       MapPublicIpOnLaunch: false # Ensures it's private
//       Tags:
//         - Key: Name
//           Value: !Sub ${ClusterName}-private-subnet-2
//         - Key: Terraform
//           Value: "true"
//         - Key: service
//           Value: ROSA
//         - Key: cluster_name
//           Value: !Ref ClusterName
//         - Key: kubernetes.io/role/internal-elb
//           Value: "1" # Tag from Terraform

//   PrivateRouteTable:
//     Type: AWS::EC2::RouteTable
//     Properties:
//       VpcId: !Ref RosaVPC
//       Tags:
//         - Key: Name
//           Value: !Sub ${ClusterName}-private-route-table
//         - Key: Terraform
//           Value: "true"
//         - Key: service
//           Value: ROSA
//         - Key: cluster_name
//           Value: !Ref ClusterName

//   PrivateSubnet1RouteTableAssociation:
//     Type: AWS::EC2::SubnetRouteTableAssociation
//     Properties:
//       SubnetId: !Ref PrivateSubnet1
//       RouteTableId: !Ref PrivateRouteTable

//   PrivateSubnet2RouteTableAssociation:
//     Type: AWS::EC2::SubnetRouteTableAssociation
//     Properties:
//       SubnetId: !Ref PrivateSubnet2
//       RouteTableId: !Ref PrivateRouteTable

//   AuthorizeInboundVpcTrafficSecurityGroup:
//     Type: AWS::EC2::SecurityGroup
//     Properties:
//       GroupDescription: Allow all inbound traffic within the VPC
//       VpcId: !Ref RosaVPC
//       SecurityGroupIngress:
//         - IpProtocol: "-1" # All protocols
//           FromPort: -1 # All ports
//           ToPort: -1 # All ports
//           CidrIp: !Ref VpcCidrBlock # Allows all traffic from within the VPC CIDR
//       SecurityGroupEgress:
//         - IpProtocol: "-1" # All protocols
//           FromPort: -1 # All ports
//           ToPort: -1 # All ports
//           CidrIp: "0.0.0.0/0" # Allow all outbound traffic (typically for VPC Endpoints)
//       Tags:
//         - Key: Name
//           Value: !Sub ${ClusterName}-inbound-vpc-sg
//         - Key: Terraform
//           Value: "true"
//         - Key: service
//           Value: ROSA
//         - Key: cluster_name
//           Value: !Ref ClusterName

//   STSVpcEndpoint:
//     Type: AWS::EC2::VPCEndpoint
//     Properties:
//       VpcId: !Ref RosaVPC
//       ServiceName: !Sub com.amazonaws.${AWS::Region}.sts
//       VpcEndpointType: Interface
//       PrivateDnsEnabled: true
//       SubnetIds:
//         - !Ref PrivateSubnet1
//         - !Ref PrivateSubnet2
//       SecurityGroupIds:
//         - !GetAtt AuthorizeInboundVpcTrafficSecurityGroup.GroupId # Referencing SG ID
//       Tags:
//         - Key: Name
//           Value: !Sub ${ClusterName}-sts-endpoint
//         - Key: Terraform
//           Value: "true"
//         - Key: service
//           Value: ROSA
//         - Key: cluster_name
//           Value: !Ref ClusterName

//   ECRApiVpcEndpoint:
//     Type: AWS::EC2::VPCEndpoint
//     Properties:
//       VpcId: !Ref RosaVPC
//       ServiceName: !Sub com.amazonaws.${AWS::Region}.ecr.api
//       VpcEndpointType: Interface
//       PrivateDnsEnabled: true
//       SubnetIds:
//         - !Ref PrivateSubnet1
//         - !Ref PrivateSubnet2
//       SecurityGroupIds:
//         - !GetAtt AuthorizeInboundVpcTrafficSecurityGroup.GroupId
//       Tags:
//         - Key: Name
//           Value: !Sub ${ClusterName}-ecr-api-endpoint
//         - Key: Terraform
//           Value: "true"
//         - Key: service
//           Value: ROSA
//         - Key: cluster_name
//           Value: !Ref ClusterName

//   ECRDkrVpcEndpoint:
//     Type: AWS::EC2::VPCEndpoint
//     Properties:
//       VpcId: !Ref RosaVPC
//       ServiceName: !Sub com.amazonaws.${AWS::Region}.ecr.dkr
//       VpcEndpointType: Interface
//       PrivateDnsEnabled: true
//       SubnetIds:
//         - !Ref PrivateSubnet1
//         - !Ref PrivateSubnet2
//       SecurityGroupIds:
//         - !GetAtt AuthorizeInboundVpcTrafficSecurityGroup.GroupId
//       Tags:
//         - Key: Name
//           Value: !Sub ${ClusterName}-ecr-dkr-endpoint
//         - Key: Terraform
//           Value: "true"
//         - Key: service
//           Value: ROSA
//         - Key: cluster_name
//           Value: !Ref ClusterName

//   S3VpcEndpoint:
//     Type: AWS::EC2::VPCEndpoint
//     Properties:
//       VpcId: !Ref RosaVPC
//       ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
//       VpcEndpointType: Gateway
//       RouteTableIds:
//         - !Ref PrivateRouteTable # Associate with the private route table
//       Tags:
//         - Key: Name
//           Value: !Sub ${ClusterName}-s3-endpoint
//         - Key: Terraform
//           Value: "true"
//         - Key: service
//           Value: ROSA
//         - Key: cluster_name
//           Value: !Ref ClusterName

// Outputs:
//   VpcId:
//     Description: The ID of the created VPC.
//     Value: !Ref RosaVPC
//     Export:
//       Name: !Sub ${AWS::StackName}-VpcId

//   PrivateSubnetIds:
//     Description: A comma-separated list of the private subnet IDs.
//     Value: !Join [",", [!Ref PrivateSubnet1, !Ref PrivateSubnet2]]
//     Export:
//       Name: !Sub ${AWS::StackName}-PrivateSubnetIds

//   PrivateRouteTableId:
//     Description: The ID of the private route table.
//     Value: !Ref PrivateRouteTable
//     Export:
//       Name: !Sub ${AWS::StackName}-PrivateRouteTableId

//   SecurityGroupId:
//     Description: The ID of the security group for internal VPC traffic.
//     Value: !GetAtt AuthorizeInboundVpcTrafficSecurityGroup.GroupId
//     Export:
//       Name: !Sub ${AWS::StackName}-SecurityGroupId
// EOF
// ----

// . Create an AWS VPC using the default CloudFormations template by running the following command:
// +
// [source,terminal]
// ----
// $ rosa create network --template-dir TEMPLATES
// ----
// endif::rosa-egress-lockdown[]

.Verification
* When completed, you receive a summary of the created resources:
+
[source,bash]
----
INFO[0140] Resources created in stack:
INFO[0140] Resource: AttachGateway, Type: AWS::EC2::VPCGatewayAttachment, ID: <gateway_id>
INFO[0140] Resource: EC2VPCEndpoint, Type: AWS::EC2::VPCEndpoint, ID: <vpce_id>
INFO[0140] Resource: EcrApiVPCEndpoint, Type: AWS::EC2::VPCEndpoint, ID: <vpce_id>
INFO[0140] Resource: EcrDkrVPCEndpoint, Type: AWS::EC2::VPCEndpoint, ID: <vpce_id>
INFO[0140] Resource: ElasticIP1, Type: AWS::EC2::EIP, ID: <IP>
INFO[0140] Resource: ElasticIP2, Type: AWS::EC2::EIP, ID: <IP>
INFO[0140] Resource: InternetGateway, Type: AWS::EC2::InternetGateway, ID: igw-016e1a71b9812464e
INFO[0140] Resource: KMSVPCEndpoint, Type: AWS::EC2::VPCEndpoint, ID: <vpce_id>
INFO[0140] Resource: NATGateway1, Type: AWS::EC2::NatGateway, ID: <nat-gateway_id>
INFO[0140] Resource: PrivateRoute, Type: AWS::EC2::Route, ID: <route_id>
INFO[0140] Resource: PrivateRouteTable, Type: AWS::EC2::RouteTable, ID: <route_id>
INFO[0140] Resource: PrivateSubnetRouteTableAssociation1, Type: AWS::EC2::SubnetRouteTableAssociation, ID: <route_id>
INFO[0140] Resource: PublicRoute, Type: AWS::EC2::Route, ID: <route_id>
INFO[0140] Resource: PublicRouteTable, Type: AWS::EC2::RouteTable, ID: <route_id>
INFO[0140] Resource: PublicSubnetRouteTableAssociation1, Type: AWS::EC2::SubnetRouteTableAssociation, ID: <route_id>
INFO[0140] Resource: S3VPCEndpoint, Type: AWS::EC2::VPCEndpoint, ID: <vpce_id>
INFO[0140] Resource: STSVPCEndpoint, Type: AWS::EC2::VPCEndpoint, ID: <vpce_id>
INFO[0140] Resource: SecurityGroup, Type: AWS::EC2::SecurityGroup, ID: <security-group_id>
INFO[0140] Resource: SubnetPrivate1, Type: AWS::EC2::Subnet, ID: <private_subnet_id-1> \ <1>
INFO[0140] Resource: SubnetPublic1, Type: AWS::EC2::Subnet, ID: <public_subnet_id-1> \ <1>
INFO[0140] Resource: VPC, Type: AWS::EC2::VPC, ID: <vpc_id>
INFO[0140] Stack rosa-network-stack-5555 created \ <2>
----
<1> These two subnet IDs are used to create your cluster when using the `rosa create cluster` command.
<2> The network stack name is used to delete the resource later.

ifdef::rosa-egress-lockdown[]
[id="rosa-hcp-vpc-subnet-tagging-rosa-network_{context}"]
== Tagging your subnets

Before you can use your VPC to create a {product-title} cluster, you must tag your VPC subnets. Automated service preflight checks verify that these resources are tagged correctly. The following table shows how to tag your resources:

[cols="3a,8a,8a", options="header"]
|===
| Resource
| Key
| Value

| Public subnet
| `kubernetes.io/role/elb`
| `1` or no value

| Private subnet
| `kubernetes.io/role/internal-elb`
| `1` or no value

|===

[NOTE]
====
You must tag at least one private subnet and one public subnet, if applicable.
====

. Tag your resources in your terminal:
.. For public subnets, run the following command:
+
[source,terminal]
----
$ aws ec2 create-tags --resources <public_subnet_id> --region <aws_region> --tags Key=kubernetes.io/role/elb,Value=1
----
.. For private subnets, run the following command:
+
[source,terminal]
----
$ aws ec2 create-tags --resources <private_subnet_id> --region <aws_region> --tags Key=kubernetes.io/role/internal-elb,Value=1
----

.Verification

* Verify that the tag is correct by running the following command:
+
[source,terminal]
----
$ aws ec2 describe-tags --filters "Name=resource-id,Values=<subnet_id>"
----
+
.Example output
+
[source,text]
----
TAGS    Name                    <subnet_id>        subnet  <prefix>-subnet-public1-us-east-1a
TAGS    kubernetes.io/role/elb  <subnet_id>        subnet  1
----

[role="_additional-resources"]
[id="additional-resources_rosa-hcp-create-network-egress-lockdown"]
.Additional resources

* link:https://aws.amazon.com/cloudformation/[AWS CloudFormation documentation]
* link:https://github.com/openshift/rosa/blob/master/cmd/create/network/templates/rosa-quickstart-default-vpc/cloudformation.yaml[Default VPC AWS CloudFormation template]
endif::rosa-egress-lockdown[]

ifeval::["{context}" == "rosa-hcp-egress-zero-install"]
:!rosa-egress-lockdown:
endif::[]