This is the third article in a series of posts about Google Cloud Platform security. The first two articles (Article I., Article II.) in the series focused on hardening possibilities on a project level with Google Cloud Platform. In this post, you can read about security settings related to virtual machine instances running on Google Compute Engine (GCE). Read this post to learn more about built-in GCE Security. Also, don’t miss the rest of this series:
Article IV.: How to Make Your Google Cloud Platform Project More Secure: GCE Network Security
Article V.: How to Make Your Google Cloud Platform project more secure: GCE OS Security
GCE Security is All About Reducing the Attack Surface
It is always good practice to only run services that are really needed and to only use the least possible privileges to run them. This way, the list of possible entry points for attackers will be shorter, thus significantly reducing the statistical possibility of a successful attack. This technique is often called reducing the attack surface.
Periodic Checking for Not Used Instances for GCE security
If you periodically review your currently running Google Compute Engine instances, then you can sometimes find ones that are not used anymore but were not decommissioned for some reason. If you delete these instances (after a backup, of course), you will see two important benefits. Your attack surface will be reduced by an old, forgotten instance, and your monthly costs will decrease.
Using the Right Service Accounts to Run Your Instances
In the second article of the series, I wrote about Service Accounts where I noted that Service Accounts are meant for programmatic use cases. They cannot be used to access the Google Cloud Console because they are only valid for Google Cloud API access. The most frequent use case is to run applications or instances inheriting the rights of a specific Service account. This way, they can access other cloud services using the rights associated with the Service account without any extra authentication. Specifically, on Google Compute Engine, every instance uses a Service account to inherit and use its rights to access different GCP services. You can define the associated service account to use for an instance during its creation or by editing the instance when it is not running.
By defining a new Service account for a set of similar instances using Identity & Access Management (IAM), you can specify very granularly the usable GCP features for those instances. For example, you can provide the “Storage Object Viewer” right to the Service account. Then the instance using that Service account will be able to read (download) all the files from all Google Cloud Storage (GCS) buckets associated with the project. In turn, if your specific use case does not require your virtual machines to have access to GCS objects, it is a good idea to revoke this right from the Service account associated with those instances. It is also important to note that these rights actually mean that there are no other layers of security between the instances and the GCP services where the access was given. So, any local, non-root user of the instance will be able to use the whole GCP service. They will not need additional keys or any form of authentication needed if the instance has rights to the service through its associated Service account. That is why it is very important to correctly set up the Service accounts for your instances.
You can read more about Service Account usage related to Google Compute Engine here.
Checking the Access Scopes of Your Instances
Another set of settings is available to control which GCP services an instance can access. This is basically a legacy system which is not required if you set up the Service account of the instance correctly. This is just another level to specify GCP service accesses on an individual instance basis if you need that.
- Known as access scopes, they are separate for each instance. The available access scopes cover most of the GCP services. The possible values for these scopes are the following:
- “full access”
Each allows the instance to do what the name suggests with the given GCP service if the Service account also allows that access. Service accounts supersede the access scopes and it is better to set up access to the GCP services using them. Still, the instance needs to have the right values for access scopes as well. If you set “disabled” as an access scope to Cloud Storage for an instance, it will not be able to access Cloud Storage. Even if the associated Service account has the appropriate rights for Cloud Storage. You can read more about instance access scopes here.
Check and Rotate the Keys in the ssh-key Metadata Object
On Linux instances, Google Compute Engine has a feature to automatically inject your users and SSH keys to a running instance so that you can access it via SSH. There are two places where the SSH keys can be added. One is the project level special metadata key named “ssh-keys”. The other is the instance level metadata key of the same name. It is possible to disable the project-level SSH keys for individual instances if you want some specific instances’ SSH access keys to be separately handled only using the instance level metadata key.
The ssh-key is a special metadata item containing one or more entries. Each entry consists of a key and a value pair. The key is the username and the value is the SSH public key string in this format: “ ”. Any public key added here will automatically create the corresponding user with the key in the authorized_keys file on all your machines. It is very important to periodically review the project-level SSH key list and also the instance level lists if you have used them previously. You should remove the unnecessary SSH keys from this list regularly. This way, the corresponding users will not be deleted from the OS. However, the key will be removed from their authorized_keys file. You can read more about SSH key handling here.