Welcome back to GCP Security and Networking Fundamentals! In this lesson, we move beyond user and group management to explore a core GCP security concept: service accounts and IAM roles. While users and groups are great for managing human access, service accounts are designed for applications and services running on Google Cloud. They provide a secure, manageable way for your workloads — such as virtual machines and serverless functions — to access other GCP resources. By the end of this lesson, you'll know how to create service accounts, grant them the right permissions, assign them to resources, and review their access, all using Python and GCP APIs.
Before we dive into implementation, let's clarify what service accounts are and why they're essential in GCP. Unlike user accounts, which represent people, a service account is a special identity intended for applications, virtual machines, or other compute workloads. Service accounts allow these workloads to authenticate to GCP APIs and access resources securely, without embedding user credentials or managing passwords.
Think of a service account as a digital identity badge for your application. When you assign a service account to a VM or a Cloud Function, that workload can act as the service account and use its permissions to interact with other GCP services. This approach keeps your environment secure and makes it easy to follow best practices like least privilege.
In GCP, access control is managed through IAM policies. You can grant permissions to service accounts, users, or groups by assigning them IAM roles on specific resources. Additionally, you can control which identities are allowed to "impersonate" or "act as" a service account by granting the roles/iam.serviceAccountUser role. This ensures that only trusted users or services can use a service account's identity to access resources.
Permissions in GCP are always explicit: you must grant a service account the necessary roles to access resources, and you must grant users or other service accounts the ability to use or manage a service account. This separation of duties helps maintain a strong security posture.
Throughout this course, Unit 2 uses the same mock GCP environment as the other units. That means all discovery clients should be built with:
os.environ.get("GCP_DISCOVERY_URL")credentials=Nonestatic_discovery=False
Why is credentials=None acceptable here? Because requests are sent to a local practice service rather than real Google Cloud APIs, so real authentication is not required.
Why do we also set static_discovery=False? Some versions of google-api-python-client can otherwise fall back to built-in discovery metadata and send requests to real Google API endpoints. In this course, we want to force the client to use the mock discovery URL so all practice code stays inside the local training environment.
In production, things work differently:
- your Python client must authenticate to Google Cloud
- the recommended approach is usually Application Default Credentials (ADC)
- when a workload runs on GCP with an attached service account, the workload can often obtain credentials automatically from the metadata service
- when running locally, ADC is commonly set up with
gcloud auth application-default loginor by using a configured service account in a secure way
So, in this lesson, remember the distinction:
- mock environment:
credentials=Noneandstatic_discovery=False
Let's create a service account that will allow a Compute Engine VM to read objects from Cloud Storage. We'll use the Google API discovery client to automate this process in the course mock environment.
In GCP, a region is a geographic area such as us-central1, and a zone is a specific deployment location inside that region, such as us-central1-a or us-central1-b.
When creating zonal resources like Compute Engine VMs, you must choose a zone. In this lesson, we use the ZONE environment variable and default it to us-central1-a simply to keep examples concrete and easy to run.
How do you choose a zone in practice?
- pick a zone in the region where you want your workload to run
- keep related resources close together when latency matters
- consider availability and redundancy if you plan to spread workloads across zones
For this course, using a configurable ZONE variable is enough. In production, you may choose zones based on architecture, quotas, service availability, and resilience requirements.
A service account without permissions can't access any resources. In GCP, you grant permissions by assigning IAM roles to the service account. GCP provides many predefined roles for common use cases, such as roles/storage.objectViewer for read-only access to Cloud Storage or roles/datastore.user for Datastore access.
You can grant roles at different levels: project, folder, or resource. For most workloads, granting a role at the project level is sufficient, but you can scope it down to a specific bucket or database for tighter security.
Predefined roles are maintained by Google and cover most common scenarios. For more granular control, you can create custom roles with exactly the permissions your workload needs.
When you create a Compute Engine VM, you can specify which service account it should use. The VM will automatically receive credentials for that service account, allowing applications running on the VM to access GCP resources according to the service account's permissions.
If you need to change the service account for an existing VM, you can do so using the Compute Engine API or the Google Cloud Console. The VM will then use the new service account's permissions for all future API calls.
Note: In real GCP environments, applications on the VM should usually rely on Application Default Credentials (ADC) rather than embedding keys in code. When a service account is attached to the VM, the workload can typically obtain credentials automatically.
- In these examples, we use predefined roles for simplicity.
- In production, follow the principle of least privilege: grant only the permissions your workload needs, and nothing more.
- You can create custom roles in GCP to specify exactly which permissions are allowed.
Example: Custom role for read-only access to a specific Cloud Storage bucket
Best practices:
- Grant roles at the lowest possible resource level (e.g., a single bucket, not the whole project).
- Regularly review service account permissions and remove unnecessary access.
Different GCP services require different service accounts and permissions. Let's create a service account for a Cloud Function that needs to write to Firestore.
This creates a service account, grants it Firestore access, and deploys a Cloud Function using that service account.
After creating service accounts and assigning roles, it's important to review their permissions and audit access. You can use the IAM API to list the roles granted to a service account.
For auditing, GCP provides Cloud Audit Logs, which record all access to resources, including which service account was used. You can review these logs in the Cloud Console or export them for analysis.
Let's put it all together: create service accounts, grant roles, assign them to resources, and inspect their permissions.
In this lesson, you've learned how GCP uses service accounts and IAM roles to manage secure, fine-grained access for applications and services. You now know how to create service accounts, grant them predefined or custom roles, assign them to resources like VMs and Cloud Functions, and review their permissions. In this course's mock environment, we build discovery clients with os.environ.get("GCP_DISCOVERY_URL"), credentials=None, and static_discovery=False so the client stays inside the mock environment. In real GCP environments, use Application Default Credentials (ADC) or another supported authentication flow. Remember to always follow the principle of least privilege: grant only the permissions needed, and regularly review access. In production, use custom roles and resource-level scoping to keep your cloud environment secure and manageable.
In the next lesson, we'll explore more advanced IAM features and best practices for securing your GCP workloads.
