Skip to content
Hosting Operations13 min read

Cloud Infrastructure Providers: 5 Security Hardening Differences

Compare security hardening across AWS, Azure, GCP, DigitalOcean, and Linode. Learn which default configurations need immediate attention.

Written by Abdul AbrorTechnical Hosting Support Engineer
a computer generated image of a computer
On this page

TL;DR — Key takeaways

  • AWS, Azure, and GCP ship with open security groups by default; DigitalOcean and Linode start with deny-all firewall rules
  • Identity and access management differs sharply: AWS uses IAM roles with granular policies, while smaller providers rely on SSH keys and API tokens
  • Network isolation approaches vary from VPC peering (AWS/GCP) to private networking overlays (DigitalOcean/Linode)
  • Encryption at rest is automatic on AWS and Azure but requires manual enablement on DigitalOcean and Linode block storage
  • Audit logging capabilities range from comprehensive (AWS CloudTrail) to basic activity logs (smaller providers)

Security hardening looks different across cloud infrastructure providers. What works on AWS will not transfer directly to Azure, and GCP's default settings differ from DigitalOcean in ways that catch teams off guard during cloud service migration.

I've handled hundreds of support tickets where mismatched security expectations caused outages or exposed data. The usual culprit? Assuming all providers ship with the same baseline protections. They don't. Each platform makes different tradeoffs between convenience and default security posture, and those differences matter the moment you provision your first instance.

The Threat Model: What You're Protecting Against

Cloud infrastructure faces five primary threat categories: unauthorized access through exposed management interfaces, lateral movement after initial compromise, data exfiltration from storage services, privilege escalation via misconfigured IAM, and resource hijacking for cryptomining or DDoS. Your hardening strategy must address all five.

Attack surface varies by provider. AWS and Azure expose hundreds of API endpoints. Smaller providers like Linode have fewer services, which means fewer potential entry points but also fewer native security controls to layer on top.

The shared responsibility model shifts based on service type. For IaaS (bare compute instances), you own everything above the hypervisor: OS patching, firewall rules, application security, encryption key management. For managed databases or container services, the provider handles more, but you still control network access and credential policies.

Default Security Posture: Five Critical Differences

AWS security groups default to deny-all inbound but allow all outbound. Sounds safe until you realize the initial wizard often adds permissive rules like 0.0.0.0/0 on port 22. I've seen production SSH exposed to the internet because someone clicked through the launch template without reading the rules.

Azure Network Security Groups behave similarly but add a twist: default rules allow inbound traffic from Azure Load Balancer and outbound to the internet. You must explicitly deny these if your threat model requires it.

GCP firewall rules apply at the VPC level, not the instance level. The default network includes an allow-internal rule that permits all RFC 1918 traffic between instances. If an attacker compromises one VM, they can pivot to others without hitting a firewall boundary unless you segment further.

DigitalOcean Cloud Firewalls ship in deny-all mode. Nothing gets through until you create an allow rule. This is stricter out of the box but also means you will lock yourself out if you forget to open SSH before applying the firewall to your droplet.

Linode does the same with their Cloud Firewall service, though it is optional. If you do not enable it, you rely solely on iptables rules you configure manually. Many users skip this step entirely, which leaves instances exposed with only SSH key authentication as protection.

Identity and Access Management: Granularity vs Simplicity

AWS IAM gives you role-based access control with policy documents that specify exact API actions. You can lock a user down to reading only S3 objects in a specific bucket with a specific prefix. This granularity is powerful but complex; teams often grant overly broad permissions because writing tight policies takes time.

Azure Active Directory integrates with managed identities for Azure resources, letting you assign roles at the subscription, resource group, or individual resource level. The learning curve is steep if you come from AWS, and the permission inheritance model behaves differently enough to cause confusion during cloud to cloud migration.

GCP uses service accounts with IAM bindings. Permissions attach at the project level by default, which can be too coarse for multi-tenant setups. You need to understand resource hierarchy (organization, folder, project) to apply least-privilege correctly.

DigitalOcean and Linode use API tokens with broad scopes. A token either has read-write access to all resources or it does not exist. There is no middle ground for scoping a token to a single droplet or a specific Linode instance. For teams used to fine-grained IAM, this feels like a step backward. SSH key management is your primary access control mechanism, which works but does not scale well past a few engineers.

  • Enable MFA on all accounts with console or API access, regardless of provider
  • Rotate API tokens and SSH keys every 90 days; set calendar reminders
  • Use separate tokens or keys per engineer and per automation script so you can revoke individually
  • Audit permission grants monthly using the provider's access logs; remove stale credentials immediately

Network Isolation and Segmentation Approaches

AWS VPCs let you define private subnets with no internet gateway, forcing traffic through NAT gateways or VPN connections. You can peer VPCs across accounts and regions, which works well for isolating production from development environments. Route tables and network ACLs add layers of control on top of security groups.

Azure VNets operate similarly but add service endpoints that let you access PaaS services like Azure SQL over the Microsoft backbone instead of the public internet. This reduces exposure but requires careful planning; service endpoint policies are not intuitive.

GCP VPCs are global by default, spanning regions automatically. Subnets are regional. Shared VPC lets you centralize network administration, but the permission model is tricky. Private Google Access allows instances without external IPs to reach Google APIs, which is useful for lockdown scenarios.

DigitalOcean's private networking creates a second network interface on each droplet that communicates over a non-internet-routable subnet. Traffic between droplets in the same datacenter region flows over this private link. It is simple but not true network isolation; any droplet in the region can reach any other unless you add firewall rules.

Linode VLANs provide layer-2 isolation, letting you group instances into broadcast domains. This is more flexible than DigitalOcean's model but requires more network knowledge to configure correctly. For cloud service migration, you need to rebuild VLANs to match your source VPC topology, which can be time-consuming.

Encryption at Rest and Key Management

AWS EBS volumes support encryption using AWS KMS keys. You can enable default encryption at the account level so all new volumes encrypt automatically. S3 buckets support server-side encryption with KMS, S3-managed keys, or customer-provided keys. The hardest part is key rotation policies; you must automate this or it gets forgotten.

Azure Disk Encryption relies on Azure Key Vault. Managed disks can encrypt using platform-managed keys or customer-managed keys. Blob storage has similar options. The integration between Key Vault and compute resources is smoother than AWS in my experience, but you still need to plan key access policies carefully.

GCP encrypts all data at rest by default using Google-managed keys. You can bring your own keys via Cloud KMS or use customer-supplied encryption keys for more control. The default encryption is transparent, which is good for simplicity but bad if you need to prove compliance with specific key custody requirements.

DigitalOcean block storage volumes support encryption, but it is not enabled by default. You must check a box during volume creation. Spaces (object storage) does not offer server-side encryption beyond what you implement at the application layer. For sensitive data, this means you need to encrypt files before uploading.

Linode block storage behaves the same way: encryption available but manual. Linode Object Storage uses S3-compatible APIs, so you can implement SSE-C (server-side encryption with customer-provided keys) if your application supports it, but there is no native KMS equivalent.

  • Enable default encryption for all storage services where the provider supports it
  • Use separate encryption keys for production, staging, and development environments
  • Test encrypted snapshot restoration before you need it in an emergency
  • Document key rotation procedures and set up automated reminders every 180 days
  • Verify encryption status after cloud to cloud migration by checking volume and bucket properties directly

Audit Logging and Monitoring Capabilities

AWS CloudTrail records every API call made in your account, including who made it, from what IP, and what the result was. Enable it in all regions and configure log file validation to detect tampering. Export logs to S3 and set up lifecycle policies to archive older entries. CloudWatch Logs can ingest application logs and trigger alerts based on patterns.

Azure Activity Log tracks resource-level operations across subscriptions. Diagnostic settings let you stream logs to Log Analytics workspaces, Event Hubs, or Storage Accounts. The integration with Azure Monitor is tighter than AWS CloudWatch, but the query language takes time to learn.

GCP Cloud Audit Logs split into Admin Activity, Data Access, System Event, and Policy Denied logs. Admin Activity logs are always on; Data Access logs must be enabled per service because they generate high volume. Export logs to Cloud Storage or BigQuery for long-term retention and analysis.

DigitalOcean provides an activity log in the control panel showing droplet actions, firewall changes, and team member activity. It is basic. There is no API call logging, no fine-grained event tracking. For serious audit requirements, you need to implement your own logging using syslog forwarding from each droplet.

Linode's event logging covers account actions like instance creation and deletion but does not track API usage in detail. The Linode CLI and API do not produce audit trails comparable to the big three providers. You must rely on OS-level logging (auditd, journalctl) and centralize those logs yourself using a tool like rsyslog or Fluentd.

Hardening Checklist: Step-by-Step Implementation

Start with network perimeter lockdown. Audit every security group, network ACL, and firewall rule. Remove any 0.0.0.0/0 source rules except where absolutely necessary (like HTTPS on a public web server). Restrict SSH and RDP to known IP ranges or a bastion host. Document exceptions.

Next, enforce MFA. On AWS, enable MFA delete for S3 buckets holding critical data. On Azure, use Conditional Access policies to require MFA for all interactive logins. On GCP, set up 2-Step Verification for all user accounts. Smaller providers lack native MFA for console access, so protect accounts with strong passwords and consider a password manager with breach monitoring.

Configure centralized logging. Point CloudTrail, Azure Activity Log, or Cloud Audit Logs to a dedicated storage location with restricted write permissions. Set up alerts for high-risk events: new IAM user creation, security group changes, instance termination, encryption key deletion. For DigitalOcean and Linode, use a third-party SIEM or log aggregator like Datadog, Splunk, or the ELK stack.

Enable encryption everywhere. Turn on default EBS encryption in AWS, managed disk encryption in Azure, and verify GCP's default encryption meets your policy. Manually enable encryption for DigitalOcean and Linode block storage volumes. Encrypt S3 and Spaces buckets. Use TLS 1.2 or higher for all data in transit; disable older protocol versions at load balancers and API gateways.

Review IAM permissions quarterly. Use access advisor tools (AWS), access reviews (Azure), or policy analyzer (GCP) to identify unused permissions. Remove them. On DigitalOcean and Linode, audit SSH keys and API tokens; delete any that belong to former team members or decommissioned automation scripts.

Verification: How to Confirm Your Hardening Worked

Run port scans against your public IPs using nmap or a cloud-native scanner like AWS Inspector. Check that only intended ports respond. Any unexpected open port is a misconfiguration.

Attempt to access resources using a low-privilege test account. You should hit permission-denied errors when trying to delete instances, modify security groups, or access storage buckets outside the test account's scope. If the test account can do more than it should, your IAM policies are too broad.

Check encryption status directly. On AWS, run `aws ec2 describe-volumes` and verify the `Encrypted` field is true. On Azure, use `az disk list --query '[].encryption'`. On GCP, check volume details in the console or via `gcloud compute disks describe`. For DigitalOcean and Linode, verify in the control panel or API response that encryption is enabled.

Review audit logs for gaps. Make a test change (like creating a new firewall rule) and confirm it appears in CloudTrail, Activity Log, or Cloud Audit Logs within five minutes. If it does not show up, your logging configuration is incomplete.

Test your backup restore process using encrypted snapshots. Spin up a new instance from an encrypted snapshot and verify you can mount the volume and read data. This confirms encryption keys are correctly stored and accessible during recovery.

Cloud Service Migration: Security Gotchas to Avoid

When you move between cloud infrastructure providers, do not assume equivalent service names mean equivalent security models. AWS security groups are stateful; GCP firewall rules are not. Azure NSGs have default rules that other providers do not. Read the documentation for the target platform before migrating.

IAM translation is manual work. Export your existing policies as JSON, map each permission to the target provider's equivalent action, and rebuild them. There is no automated converter that handles edge cases correctly. Budget extra time for testing.

Network topology changes. If you used VPC peering or VPN connections heavily on AWS, you will need to rearchitect around Azure VNet peering or GCP's Shared VPC. DigitalOcean and Linode lack native VPN services; you must deploy your own using WireGuard or OpenVPN.

Encryption key custody shifts during cloud to cloud migration. If you used customer-managed keys in AWS KMS, you cannot export the key material to Azure Key Vault or GCP Cloud KMS. You must re-encrypt data with new keys in the target environment. Plan for downtime or a phased migration where you decrypt in the source, transfer, and re-encrypt at the destination.

Quick troubleshooting checklist

  • Audit all security groups and firewall rules immediately after provisioning any instance
  • Enable MFA on root accounts and administrative users across all cloud infrastructure providers
  • Configure encryption at rest for all block storage volumes and object storage buckets
  • Set up centralized logging for API calls, authentication events, and network flow data
  • Review IAM policies or SSH key permissions quarterly; remove unused credentials
  • Test backup restoration procedures monthly to verify encrypted snapshots work
  • Enable automatic security updates for OS packages on all compute instances
  • Document egress filtering rules and verify outbound traffic controls are active

FAQ

Which cloud infrastructure providers have the strictest default security settings?

DigitalOcean and Linode ship with deny-all firewall rules by default, requiring you to explicitly open ports. AWS, Azure, and GCP create security groups that often allow broader access ranges, which means you must lock them down manually during initial setup. No provider enables encryption at rest by default across all services.

How do I audit security configurations during cloud to cloud migration?

Export security group rules, IAM policies, and firewall configurations from your source provider using their CLI tools. Compare network ingress rules line by line against your documented security baseline. Check encryption settings on storage volumes and verify logging is active before migrating workloads. Test authentication flows in the target environment using non-production credentials first.

What are the biggest security gaps when moving between cloud service migration paths?

IAM translation is the hardest part. AWS IAM roles do not map directly to Azure managed identities or GCP service accounts. SSH key management differs sharply across providers, and smaller platforms lack fine-grained permission systems entirely. Network ACLs and security group logic varies enough that you cannot copy rules verbatim; you need to rebuild them based on the target provider's model.