Skip to content

Commit

Permalink
feat(api-gateway): Enable API Key authentication (#35)
Browse files Browse the repository at this point in the history
* feat(api-gateway): enable API key functionality

* Change for_each to count

* fix(api-gateway): change back to for_each

* feat(api-gateway): fix looping

* revert

* Change to count?

* Goodbye api_keys

* fix(api-gateway): enforce service account max length
  • Loading branch information
royal authored Oct 26, 2023
1 parent 29cf3ae commit 22b6d61
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 36 deletions.
19 changes: 17 additions & 2 deletions gcp/api-gateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,40 @@ This Terraform module allows you to set up an API Gateway on Google Cloud Platfo
2. Terraform installed
3. Google Cloud SDK (Optional)

You will also need to ensure the following APIs are enabled in your GCP project:
- apigateway.googleapis.com
- servicecontrol.googleapis.com
- servicemanagement.googleapis.com
- serviceusage.googleapis.com
- apikeys.googleapis.com

and grant these roles for your cloud build service account:
- roles/apigateway.admin
- roles/serviceusage.serviceUsageAdmin
- roles/serviceusage.apiKeysAdmin

This can be done in the [infrastructure](https://github.com/NandosUK/infrastructure/blob/master/gcp/organization/environment/inputs-for-unrestricted.auto.tfvars) repository, where your project is defined.

## Resources Created

- Google Cloud Service Account for the API Gateway
- API Gateway API Resource
- API Gateway API Config
- API Gateway with regional deployment
- API Keys to authenticate calls and add resource quotas

## Usage

Refer to the example Terraform script in the example folder for a demonstration on how to use this updated module.

Example of use:

[test/gcp/api-gateway.tf](https://chat.openai.com/test/gcp/api-gateway.tf)
[test/gcp/api-gateway.tf](../../test/gcp/api-gateway.tf)

Make sure you have a Open API spec file that defines your API:

You can find one here:

[test/assets/api-gateway-example.yml](test/assets/api-gateway-example.yml)
[test/assets/api-gateway-example.yml](../../test/assets/api-gateway-example.yml)

Also we enable a [Backstage template](https://backstage.nandos.dev/create) to generate a custom one.
63 changes: 29 additions & 34 deletions gcp/api-gateway/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ locals {
domains = [var.environment == "prod" ? "${var.api_name}.api.nandos.dev" : var.environment == "preview" ? "${var.api_name}-preview.api.nandos.dev" : "${var.api_name}-preprod.api.nandos.dev"]
}


# Create a service account for the API Gateway
resource "google_service_account" "api_gateway_sa" {
account_id = "${var.api_name}-api-gateway-sa"
account_id = "${substr("${var.api_name}-api-gateway", 0, 25)}-sa"
display_name = "API Gateway ${var.api_name}"
project = var.project_id
}
Expand Down Expand Up @@ -60,35 +59,34 @@ resource "google_api_gateway_gateway" "nandos_api_gateway" {
region = var.project_region
}

# TODO: enable add keys via TF
/* # Enable the api so we can generate keys against it
resource "google_project_service" "enable_api_gateway" {
service = google_api_gateway_api.nandos_api.managed_service
disable_on_destroy = false # Set to 'true' if you want to disable the service when destroying this Terraform resource
}
resource "google_apikeys_key" "primary" {
name = "key-my-test-123"
display_name = "Key for XXX 123"
project = var.project_id
restrictions {
api_targets {
service = google_api_gateway_api.nandos_api.managed_service
methods = ["GET*"]
}
server_key_restrictions {
allowed_ips = ["127.0.0.1"]
}
}
depends_on = [
google_project_service.enable_api_gateway
]
} */

# in development: api keys
# resource "google_project_service" "enable_api_gateway" {
# service = google_api_gateway_api.nandos_api.managed_service
# project = var.project_id
# disable_on_destroy = false
# }

# resource "google_apikeys_key" "api_keys" {
# count = length(var.api_keys)

# name = "key-${var.api_keys[count.index].name}"
# display_name = var.api_keys[count.index].display_name
# project = var.project_id

# restrictions {
# api_targets {
# service = google_api_gateway_api.nandos_api.managed_service
# methods = var.api_keys[count.index].methods
# }

# dynamic "server_key_restrictions" {
# for_each = var.api_keys[count.index].allowed_ips != null ? [1] : []
# content {
# allowed_ips = var.api_keys[count.index].allowed_ips
# }
# }
# }
# }

resource "google_compute_region_network_endpoint_group" "api_g_neg" {
provider = google-beta
Expand All @@ -114,7 +112,6 @@ resource "google_compute_url_map" "urlmap" {
name = "${var.api_name}-urlmap"
description = "URL map for ${var.api_name}"
default_service = google_compute_backend_service.api_g_backend_service.id

}

resource "google_compute_managed_ssl_certificate" "default" {
Expand All @@ -129,10 +126,8 @@ resource "google_compute_managed_ssl_certificate" "default" {
lifecycle {
create_before_destroy = true
}

}


resource "google_compute_target_https_proxy" "default" {
project = var.project_id
name = "${var.api_name}-https-proxy"
Expand Down
11 changes: 11 additions & 0 deletions gcp/api-gateway/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,14 @@ variable "environment" {
error_message = "The environment must be one of: preview, preprod, dev or prod."
}
}

# variable "api_keys" {
# description = "List of API keys configurations. This is only needed if you require 3rd party access."
# type = list(object({
# name = string
# display_name = string
# methods = list(string)
# allowed_ips = optional( list(string))
# }))
# default = []
# }
7 changes: 7 additions & 0 deletions test/gcp/api-gateway.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,11 @@ module "api-gateway-api-1" {
openapi_spec_file_path = "../assets/api-gateway-example.yml"
project_region = "europe-west2"
environment = "preview"
# api_keys = [
# {
# name = "default"
# display_name = "Default API Key for testing"
# methods = ["GET*"]
# },
# ]
}

0 comments on commit 22b6d61

Please sign in to comment.