Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
.vscode/

credentials*.json
.run/
.run/


__pycache__/
1 change: 1 addition & 0 deletions deployment-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ This is a checklist for deploying a new realm and setting up the first environme
- [ ] Run the setup_env.py script. [docs](deployment-procedure.md#step-48-run-the-setuppy-script)
- [ ] Prepare and Deploy the Environment. [docs](deployment-procedure.md#step-49-prepare-and-deploy-the-environment)
- [ ] Configure the Auth Domains & Email Templates. [docs](deployment-procedure.md#step-410-configure-the-auth-domains-and-email-templates-for-the-identity-platform)
- [ ] (Optional) Add a backend NAT IP address into the MongoDB cluster access list. [docs](deployment-procedure.md#step-411-add-a-backend-nat-ip-address-into-the-mongodb-cluster-access-list)
6 changes: 5 additions & 1 deletion deployment-procedure.md
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,11 @@ flowchart

The auth domains are configured automatically during the deployment process.

However, to show the `%APP_NAME%` in the email templates, for example, in the verification email you have to manually enable the consent-/branding-screen in the Google cloud console for the **environment project** and set the app name there. Even if the project uses a different OAuth project, the app name is taken from the environment project's consent screen (seems like a bug in the firebase).
However, to show the `%APP_NAME%` in the email templates, for example, in the verification email you have to manually enable the consent-/branding-screen in the Google Cloud console for the **environment project** and set the app name there. Even if the project uses a different OAuth project, the app name is taken from the environment project's consent screen (seems like a bug in the firebase).

### Step 4.11: Add a backend NAT IP address into the MongoDB cluster access list.

For security reasons, you can add a backend NAT IP address into the MongoDB cluster access list. It will be exported as an environment variable in the backend pulumi outputs.

## How to

Expand Down
64 changes: 61 additions & 3 deletions iac/backend/deploy_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ def _get_fully_qualified_image_name(
docker_repository: pulumi.Output[gcp.artifactregistry.Repository],
tag: str
) -> pulumi.Output[str]:

def _get_self_link(repository_info):
# Get the latest docker image with this tag.
# Given the actual tag may be assigned to another image, we need to get the latest image with this tag.
Expand All @@ -220,13 +219,60 @@ def _get_self_link(repository_info):
project=repository_project_id
)

pulumi.info("Deploying image with the link: "+ image.self_link)
pulumi.info("Deploying image with the link: " + image.self_link)

return image.self_link

return docker_repository.apply(_get_self_link)


def _setup_nat_gateway(*,
basic_config: ProjectBaseConfig
) -> tuple[gcp.compute.Network, gcp.compute.Subnetwork, list[pulumi.Resource]]:
"""
Sets up a NAT Gateway in Google Cloud Platform.
This is used so that all our cloud run instances route their requests through this NAT gateway with a static ip address.
ref: https://docs.cloud.google.com/run/docs/configuring/static-outbound-ip
"""
network = gcp.compute.Network(
get_resource_name(resource="nat-gateway", resource_type="network"),
auto_create_subnetworks=False,
opts=pulumi.ResourceOptions(provider=basic_config.provider))

sub_net = gcp.compute.Subnetwork(
get_resource_name(resource="nat-gateway", resource_type="sub-network"),
# Minimum /26 recommended for Cloud Run because ip addresses may change depending on the scaling of instances.
# ref: https://docs.cloud.google.com/run/docs/configuring/vpc-direct-vpc#scale_up_and_scale_down
ip_cidr_range="10.0.0.0/26",
region=basic_config.location,
network=network.id,
opts=pulumi.ResourceOptions(provider=basic_config.provider, depends_on=[network]))

static_ip = gcp.compute.Address(get_resource_name(resource="nat-gateway", resource_type="static-ip"),
region=basic_config.location,
opts=pulumi.ResourceOptions(provider=basic_config.provider))

router = gcp.compute.Router(
get_resource_name(resource="nat-gateway", resource_type="router"),
network=network.id,
region=basic_config.location,
opts=pulumi.ResourceOptions(provider=basic_config.provider, depends_on=[network])
)

router_nat = gcp.compute.RouterNat(
get_resource_name(resource="nat-gateway", resource_type="nat"),
router=router.name,
nat_ip_allocate_option="MANUAL_ONLY",
nat_ips=[static_ip.id],
region=basic_config.location,
source_subnetwork_ip_ranges_to_nat="ALL_SUBNETWORKS_ALL_IP_RANGES",
opts=pulumi.ResourceOptions(provider=basic_config.provider, depends_on=[router, sub_net, network]))

# export the static IP since it might be used two whitelist the cloud run instances.
pulumi.export("cloudrun_nat_gateway_egress_static_ip", static_ip.address)
return network, sub_net, [router_nat]


# Deploy cloud run service
# See https://cloud.google.com/run/docs/overview/what-is-cloud-run for more information
def _deploy_cloud_run_service(
Expand All @@ -237,6 +283,8 @@ def _deploy_cloud_run_service(
dependencies: list[pulumi.Resource],
cv_bucket_name: Output[str],
):
nat_network, nat_sub_network, nat_dependencies = _setup_nat_gateway(basic_config=basic_config)

# See https://cloud.google.com/run/docs/securing/service-identity#per-service-identity for more information
# Create a service account for the Cloud Run service
service_account = gcp.serviceaccount.Account(
Expand Down Expand Up @@ -377,8 +425,18 @@ def _deploy_cloud_run_service(
)
],
service_account=service_account.email,
vpc_access=gcp.cloudrunv2.ServiceTemplateVpcAccessArgs(
network_interfaces=[
gcp.cloudrunv2.ServiceTemplateVpcAccessNetworkInterfaceArgs(
network=nat_network.id,
subnetwork=nat_sub_network.id,
)
],
# All traffic in the system should pass through the network
egress="ALL_TRAFFIC",
)
),
opts=pulumi.ResourceOptions(depends_on=dependencies + [iam_member], provider=basic_config.provider),
opts=pulumi.ResourceOptions(depends_on=dependencies + nat_dependencies + [iam_member], provider=basic_config.provider),
)
pulumi.export("cloud_run_url", service.uri)
return service, service_account
Expand Down