Check ID: networking_security_group_allows_ssh_from_internet
Provider: OpenStack
Service: networking
Severity: HIGH
Categories: internet-exposed, trust-boundaries
Resource type: OS::Neutron::SecurityGroup

What this check verifies

OpenStack security groups are evaluated to verify that SSH (port 22) is not exposed to the Internet (0.0.0.0/0 or ::/0). Security groups act as virtual firewalls controlling instance traffic. Unrestricted SSH access violates least privilege and creates significant attack surface. Best practices recommend restricting SSH to known IP ranges, bastion hosts, or VPN gateways.

Risk

Unrestricted SSH exposes instances to brute-force attacks, password testing, and SSH vulnerability exploitation (CVE-2023-38408, CVE-2021-41617) for initial access. Compromised instances enable persistence, privilege escalation, lateral movement, crypto mining, DDoS botnets, data exfiltration, and ransomware deployment. SSH exposure bypasses defense-in-depth and enables direct production access.

Recommendation

Restrict SSH access to known IP ranges using bastion hosts or VPN gateways instead of allowing 0.0.0.0/0. Implement multi-factor authentication, disable password authentication, and use SSH certificates for centralized key management. Monitor SSH logs for failed login attempts and enforce fail2ban or similar IP blocking mechanisms.

Remediation

# Terraform: restrict SSH to known IP ranges, never 0.0.0.0/0

resource "openstack_networking_secgroup_v2" "app_servers" {
  name        = "app-servers-sg"
  description = "Security group for application servers"
}

# GOOD: SSH restricted to corporate office IP
resource "openstack_networking_secgroup_rule_v2" "ssh_from_office" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 22
  port_range_max    = 22
  remote_ip_prefix  = "203.0.113.0/24"  # Corporate office network
  security_group_id = openstack_networking_secgroup_v2.app_servers.id
}

# GOOD: SSH from bastion security group (reference-based rule)
resource "openstack_networking_secgroup_rule_v2" "ssh_from_bastion" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 22
  port_range_max    = 22
  remote_group_id   = openstack_networking_secgroup_v2.bastion.id  # Reference, not CIDR
  security_group_id = openstack_networking_secgroup_v2.app_servers.id
}

# Bastion security group (least privilege)
resource "openstack_networking_secgroup_v2" "bastion" {
  name        = "bastion-sg"
  description = "Security group for bastion host - only entry point for SSH"
}

resource "openstack_networking_secgroup_rule_v2" "bastion_ssh" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 22
  port_range_max    = 22
  remote_ip_prefix  = var.corporate_cidr  # e.g., 203.0.113.0/24
  security_group_id = openstack_networking_secgroup_v2.bastion.id
}

# BAD: Never do this - SSH from anywhere (0.0.0.0/0)
# resource "openstack_networking_secgroup_rule_v2" "ssh_from_anywhere" {
#   direction         = "ingress"
#   ethertype         = "IPv4"
#   protocol          = "tcp"
#   port_range_min    = 22
#   port_range_max    = 22
#   remote_ip_prefix  = "0.0.0.0/0"  # DANGEROUS - DO NOT USE
#   security_group_id = openstack_networking_secgroup_v2.app_servers.id
# }

References

Where this check fires

This check runs on every scheduled scan against your OpenStack account. Findings appear at Cloud Security → Findings filterable by Check ID = networking_security_group_allows_ssh_from_internet. To re-evaluate after a fix, hit Run now on the account’s schedule under Cloud Security → Schedules — the next scan re-checks this control and marks the finding fixed or keeps it persistent.
← Back to OpenStack checks