Practicing the principle of least privilege
When it comes to security, managing access is a foundational capability—whether you’re talking about a physical space or your cloud infrastructure. If you were securing an office, you wouldn’t give every employee a master key that can open the front door, the mailbox, and the safe. Likewise, when you’re securing your cloud infrastructure, you should limit employees’ access based on their role and what they require to do their job.
This concept is known as the principle of least privilege, which NIST’s Computer Security Resource Center defines as: “A security principle that restricts the access privileges of authorized personnel… to the minimum necessary to perform their jobs.” In practice, this means assigning credentials and privileges only as needed to both users and services, and removing any permissions that are no longer necessary.
Keeping the principle of least privilege in mind, here are five practical tips to minimize the surface area of exposed resources on Google Cloud Platform (GCP) and defend against some common attacks.
#1: Avoid excessive use of broad primitive roles
Primitive roles like Owner and Editor grant wide-ranging access to all project resources. To tighten access security, consider using more specific predefined roles in Cloud Identity and Access Management (IAM), or defining custom roles that are better suited to your organization. For example, if you have a Cloud SQL database, instead of granting the project-wide Editor role to everybody, you could grant the cloudsql.editor role to users who create new databases, cloudsql.client to those who only need to connect to existing databases, and limit cloudsql.admin to database administrators.
Our policy design page has some sample structures and policies for different types of organizations, including startups, large enterprises, and education and training customers.
#2: Assign roles to groups, not individuals
If you assign an IAM role directly to an individual, they retain the rights granted by that role even if they change roles, move around your organization, or no longer require them. A safer and more maintainable option is to place users into logical groups. For example, to manage databases, you could create db-editors, db-viewers, and db-admins groups, and let users inherit roles from these groups:
An example of assigning users and roles to groups.
Groups can be created within the Admin Console for any G Suite domain, or federated from an external tool like Active Directory. By using groups for ownership, you can also avoid “orphaned” projects and resources—where a project or resource has a single owner who leaves the organization.
You can assign roles at the organization, folder, project, or resource level. This lets larger organizations easily manage roles for, say, a specific developer team or the entire accounting department. Be aware, however, that a child resource cannot limit roles granted by a parent: a user’s project-level cloudsql.viewer role, for example, will override any resource-level restrictions on any database in the same project.
#3: Reduce the risks of default service account behavior
Service accounts are a special type of account intended for apps that need to access data. If the app’s own private credentials are compromised, however, the attacker then has all the access granted to the app by the service account’s roles.
The Compute Engine default service account, which has the editor role, is enabled for all instances created in a project unless you specify otherwise.
The default service account has editor-level access to all project resources.
Creating a custom service account to use for creating instances and limiting its roles to the minimum necessary significantly reduces risk. For example, many apps using Cloud SQL only need the cloudsql.client role that lets them connect to an existing database.
With custom service accounts, you can grant the minimum privileges needed for instances and apps.
An alternative approach is to grant the instance service account minimal privileges and create dedicated service accounts for your apps. This gives you more fine-grained control over each app’s privileges, although you will need to carefully manage the service account credentials.
#4: Reduce risk and control access to your project by using networking features
To enable inter-resource communication, new GCP projects initially have a default network connecting all resources in that project. This is convenient for development, but in this default configuration, if an attacker gains unauthorized access to one resource, they may be able to reach others as well.
To limit this risk, don’t use the default network in production and explicitly specify accepted source IP ranges, ports, and protocols in network firewalls. You should also separate sensitive apps into individual virtual private clouds (VPCs), and if inter-app connectivity is required, use a Shared VPC. In each VPC, use different subnets for public facing services (e.g., web servers and bastion hosts) and private backend services. Allocate public IPs only to instances in the public subnet and add firewall rules with network tags to control which services can communicate with each other. Finally, grant permission to create or modify firewalls and routes only to those directly responsible for the network.
An example of limiting access with firewalls and separate public and private subnetworks.
The Secure Instances and Apps with Custom Networks codelab walks you through setting up the public/private subnet configuration above. The Policy design for customers article we mentioned earlier also contains sample network designs for common use cases. For guidance on the tradeoffs of single, multiple, and shared VPCs, see Best practices and reference architectures for VPC design.
#5: Consider using managed platforms and services
If you deploy and manage your own applications, you are responsible for security configuration, including the maintenance of accounts and permissions. You can limit your responsibilities by hosting your apps on managed platforms like Cloud Run, App Engine, or Cloud Functions, or by using fully managed services for databases and processing frameworks like Cloud SQL for MySQL and Postgres, Cloud Dataproc for Hadoop and Spark, and Cloud Memorystore for Redis.
A final note
Security is a priority in all aspects of Google Cloud, but cloud security is a shared responsibility, and ultimately you are responsible for making the right configuration and product choices for your organization to protect your data on GCP. These tips are a great starting point to help reduce your attack surface and help you make more informed risk decisions. For more resources and security solutions for your business, be sure to check out our Trust & Security page.