Google Cloud Platform Container Security
Google Cloud Platform Container Security
Google Cloud Platform offers Cloud Run for serverless containers and Google Kubernetes Engine (GKE) for managed Kubernetes. GCP's security model emphasizes defense in depth with Binary Authorization, Container Analysis, and GKE Autopilot mode. These services provide comprehensive security capabilities when integrated properly.
Cloud Run security benefits from Google's infrastructure security while simplifying deployment. Automatic TLS termination, IAM integration, and VPC connectivity provide enterprise security features. Binary Authorization ensures only verified images deploy. However, the serverless model limits some traditional security controls. Organizations must understand these constraints when designing security architectures.
# Example: Secure GKE deployment with Terraform
terraform {
required_version = ">= 1.0"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
google-beta = {
source = "hashicorp/google-beta"
version = "~> 5.0"
}
}
}
variable "project_id" {
description = "GCP Project ID"
type = string
}
variable "region" {
description = "GCP Region"
type = string
default = "us-central1"
}
variable "environment" {
description = "Environment name"
type = string
default = "production"
}
# Enable required APIs
resource "google_project_service" "required_apis" {
for_each = toset([
"container.googleapis.com",
"compute.googleapis.com",
"monitoring.googleapis.com",
"logging.googleapis.com",
"binaryauthorization.googleapis.com",
"containeranalysis.googleapis.com",
"containerscanning.googleapis.com",
"artifactregistry.googleapis.com"
])
project = var.project_id
service = each.key
}
# Create VPC network
resource "google_compute_network" "gke_network" {
name = "${var.environment}-gke-network"
project = var.project_id
auto_create_subnetworks = false
}
# Create subnet with secondary ranges
resource "google_compute_subnetwork" "gke_subnet" {
name = "${var.environment}-gke-subnet"
project = var.project_id
region = var.region
network = google_compute_network.gke_network.id
ip_cidr_range = "10.0.0.0/20"
secondary_ip_range {
range_name = "pods"
ip_cidr_range = "10.4.0.0/14"
}
secondary_ip_range {
range_name = "services"
ip_cidr_range = "10.0.16.0/20"
}
private_ip_google_access = true
log_config {
aggregation_interval = "INTERVAL_5_SEC"
flow_sampling = 0.5
metadata = "INCLUDE_ALL_METADATA"
}
}
# Create Cloud NAT for private nodes
resource "google_compute_router" "nat_router" {
name = "${var.environment}-nat-router"
project = var.project_id
region = var.region
network = google_compute_network.gke_network.id
}
resource "google_compute_router_nat" "nat_gateway" {
name = "${var.environment}-nat-gateway"
project = var.project_id
region = var.region
router = google_compute_router.nat_router.name
nat_ip_allocate_option = "AUTO_ONLY"
source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"
log_config {
enable = true
filter = "ERRORS_ONLY"
}
}
# Create Artifact Registry
resource "google_artifact_registry_repository" "container_registry" {
provider = google-beta
project = var.project_id
location = var.region
repository_id = "${var.environment}-containers"
format = "DOCKER"
cleanup_policies {
id = "keep-recent-versions"
action = "KEEP"
most_recent_versions {
keep_count = 10
}
}
cleanup_policies {
id = "delete-old-versions"
action = "DELETE"
condition {
older_than = "2592000s" # 30 days
}
}
}
# Create service account for GKE nodes
resource "google_service_account" "gke_node_sa" {
project = var.project_id
account_id = "${var.environment}-gke-node-sa"
display_name = "GKE Node Service Account"
}
# Grant minimal permissions to node service account
resource "google_project_iam_member" "gke_node_permissions" {
for_each = toset([
"roles/logging.logWriter",
"roles/monitoring.metricWriter",
"roles/monitoring.viewer",
"roles/artifactregistry.reader"
])
project = var.project_id
role = each.key
member = "serviceAccount:${google_service_account.gke_node_sa.email}"
}
# Create GKE cluster with security features
resource "google_container_cluster" "secure_cluster" {
provider = google-beta
name = "${var.environment}-secure-gke"
project = var.project_id
location = var.region
# Use release channel for automatic upgrades
release_channel {
channel = "REGULAR"
}
# Remove default node pool
remove_default_node_pool = true
initial_node_count = 1
# Network configuration
network = google_compute_network.gke_network.name
subnetwork = google_compute_subnetwork.gke_subnet.name
networking_mode = "VPC_NATIVE"
ip_allocation_policy {
cluster_secondary_range_name = "pods"
services_secondary_range_name = "services"
}
# Private cluster configuration
private_cluster_config {
enable_private_nodes = true
enable_private_endpoint = false
master_ipv4_cidr_block = "172.16.0.0/28"
master_global_access_config {
enabled = true
}
}
# Security configurations
master_auth {
client_certificate_config {
issue_client_certificate = false
}
}
master_authorized_networks_config {
cidr_blocks {
cidr_block = "10.0.0.0/8"
display_name = "internal-networks"
}
gcp_public_cidrs_access_enabled = false
}
# Enable security features
enable_shielded_nodes = true
enable_binary_authorization = true
enable_intranode_visibility = true
enable_l4_ilb_subsetting = true
# Workload Identity
workload_identity_config {
workload_pool = "${var.project_id}.svc.id.goog"
}
# Security posture
security_posture_config {
mode = "ENTERPRISE"
vulnerability_mode = "VULNERABILITY_ENTERPRISE"
}
# Cluster addons
addons_config {
http_load_balancing {
disabled = false
}
horizontal_pod_autoscaling {
disabled = false
}
network_policy_config {
disabled = false
}
gce_persistent_disk_csi_driver_config {
enabled = true
}
config_connector_config {
enabled = true
}
gcs_fuse_csi_driver_config {
enabled = true
}
}
# Maintenance window
maintenance_policy {
recurring_window {
start_time = "2023-01-01T00:00:00Z"
end_time = "2023-01-01T04:00:00Z"
recurrence = "FREQ=WEEKLY;BYDAY=SU"
}
}
# Logging and monitoring
cluster_telemetry {
type = "ENABLED"
}
logging_config {
enable_components = [
"SYSTEM_COMPONENTS",
"WORKLOADS",
"APISERVER",
"CONTROLLER_MANAGER",
"SCHEDULER"
]
}
monitoring_config {
enable_components = [
"SYSTEM_COMPONENTS",
"WORKLOADS",
"APISERVER",
"CONTROLLER_MANAGER",
"SCHEDULER"
]
managed_prometheus {
enabled = true
}
}
# Resource usage export
resource_usage_export_config {
enable_network_egress_metering = true
bigquery_destination {
dataset_id = "${var.environment}_gke_usage"
}
}
# Network policy
network_policy {
enabled = true
provider = "CALICO"
}
# Database encryption
database_encryption {
state = "ENCRYPTED"
key_name = google_kms_crypto_key.gke_db_key.id
}
depends_on = [google_project_service.required_apis]
}
# Create node pool with security configurations
resource "google_container_node_pool" "secure_node_pool" {
provider = google-beta
name = "${var.environment}-secure-pool"
project = var.project_id
location = var.region
cluster = google_container_cluster.secure_cluster.name
initial_node_count = 3
autoscaling {
min_node_count = 3
max_node_count = 10
location_policy = "BALANCED"
}
management {
auto_repair = true
auto_upgrade = true
}
node_config {
machine_type = "n2-standard-4"
disk_size_gb = 100
disk_type = "pd-ssd"
# Use custom service account
service_account = google_service_account.gke_node_sa.email
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform"
]
# Security configurations
shielded_instance_config {
enable_secure_boot = true
enable_integrity_monitoring = true
}
workload_metadata_config {
mode = "GKE_METADATA"
}
image_type = "COS_CONTAINERD"
metadata = {
disable-legacy-endpoints = "true"
}
labels = {
environment = var.environment
security = "hardened"
}
tags = ["gke-node", "${var.environment}-node"]
}
}
# Binary Authorization policy
resource "google_binary_authorization_policy" "cluster_policy" {
provider = google-beta
project = var.project_id
global_policy_evaluation_mode = "ENABLE"
default_admission_rule {
evaluation_mode = "REQUIRE_ATTESTATION"
enforcement_mode = "ENFORCED_BLOCK_AND_AUDIT_LOG"
require_attestations_by = [
google_binary_authorization_attestor.prod_attestor.name
]
}
cluster_admission_rules {
cluster = google_container_cluster.secure_cluster.id
evaluation_mode = "REQUIRE_ATTESTATION"
enforcement_mode = "ENFORCED_BLOCK_AND_AUDIT_LOG"
require_attestations_by = [
google_binary_authorization_attestor.prod_attestor.name
]
}
}
# Create Binary Authorization attestor
resource "google_binary_authorization_attestor" "prod_attestor" {
provider = google-beta
project = var.project_id
name = "${var.environment}-attestor"
attestation_authority_note {
note_reference = google_container_analysis_note.attestor_note.name
public_keys {
id = data.google_kms_crypto_key_version.attestor_key_version.id
pkix_public_key {
public_key_pem = data.google_kms_crypto_key_version.attestor_key_version.public_key[0].pem
signature_algorithm = data.google_kms_crypto_key_version.attestor_key_version.public_key[0].algorithm
}
}
}
}
# Output important values
output "cluster_endpoint" {
value = google_container_cluster.secure_cluster.endpoint
sensitive = true
description = "GKE cluster endpoint"
}
output "artifact_registry" {
value = "${var.region}-docker.pkg.dev/${var.project_id}/${google_artifact_registry_repository.container_registry.repository_id}"
description = "Artifact Registry URL"
}