IAM (Identity and Access Management)¶
IAM (Identity and Access Management) is a service that allows you to manage access control to your Google Cloud resources. The IdentityAccessManager
and IAMCredentials
classes in gcp-pilot provide high-level interfaces for interacting with Google Cloud IAM.
Installation¶
To use the IAM functionality, you need to install gcp-pilot with the iam extra:
Usage¶
IdentityAccessManager¶
The IdentityAccessManager
class allows you to manage service accounts and their keys, as well as IAM policies.
Initialization¶
from gcp_pilot.iam import IdentityAccessManager
iam = IdentityAccessManager() # (1)!
iam = IdentityAccessManager(project_id="my-project") # (2)!
iam = IdentityAccessManager(impersonate_account="service-account@project-id.iam.gserviceaccount.com") # (3)!
- Initialize with default credentials
- Initialize with specific project
- Initialize with service account impersonation
Managing Service Accounts¶
service_account = iam.create_service_account( # (1)!
name="my-service-account",
display_name="My Service Account",
project_id="my-project", # (2)!
exists_ok=True, # (3)!
)
print(f"Service Account: {service_account['email']}")
service_account = iam.get_service_account( # (4)!
name="my-service-account",
project_id="my-project", # (5)!
)
print(f"Service Account: {service_account['email']}")
service_accounts = iam.list_service_accounts( # (6)!
project_id="my-project", # (7)!
)
for account in service_accounts:
print(f"Service Account: {account['email']}")
- Create a service account
- Optional: defaults to the project associated with credentials
- Optional: if True, returns the existing service account if it already exists
- Get a service account
- Optional: defaults to the project associated with credentials
- List all service accounts in a project
- Optional: defaults to the project associated with credentials
Managing Service Account Keys¶
key = iam.create_key( # (1)!
service_account_name="my-service-account",
project_id="my-project", # (2)!
)
print(f"Key ID: {key['id']}")
print(f"Private Key JSON: {key['json']}")
keys = iam.list_keys( # (3)!
service_account_name="my-service-account",
project_id="my-project", # (4)!
)
for key_item in keys: # Renamed key to key_item to avoid conflict with variable 'key' later
print(f"Key ID: {key_item['id']}")
print(f"Valid After: {key_item['validAfterTime']}")
print(f"Valid Before: {key_item['validBeforeTime']}")
key = iam.get_key( # (5)!
key_id="key-id",
service_account_name="my-service-account",
project_id="my-project", # (6)!
)
print(f"Key ID: {key['id']}")
print(f"Valid After: {key['validAfterTime']}")
print(f"Valid Before: {key['validBeforeTime']}")
iam.delete_key( # (7)!
key_id="key-id",
service_account_name="my-service-account",
project_id="my-project", # (8)!
)
- Create a key for a service account
- Optional: defaults to the project associated with credentials
- List keys for a service account
- Optional: defaults to the project associated with credentials
- Get a specific key
- Optional: defaults to the project associated with credentials
- Delete a key
- Optional: defaults to the project associated with credentials
Managing IAM Policies¶
policy = iam.get_policy( # (1)!
email="my-service-account@my-project.iam.gserviceaccount.com",
project_id="my-project", # (2)!
)
print(f"Policy: {policy}")
policy = iam.bind_member( # (3)!
target_email="my-service-account@my-project.iam.gserviceaccount.com",
member_email="user@example.com",
role="roles/iam.serviceAccountUser",
project_id="my-project", # (4)!
)
print(f"Updated Policy: {policy}")
policy = iam.remove_member( # (5)!
target_email="my-service-account@my-project.iam.gserviceaccount.com",
member_email="user@example.com",
role="roles/iam.serviceAccountUser",
project_id="my-project", # (6)!
)
print(f"Updated Policy: {policy}")
policy = iam.set_policy( # (7)!
email="my-service-account@my-project.iam.gserviceaccount.com",
policy=custom_policy, # (8)!
project_id="my-project", # (9)!
)
print(f"Updated Policy: {policy}")
- Get the IAM policy for a service account
- Optional: defaults to the project associated with credentials
- Bind a member to a role for a service account
- Optional: defaults to the project associated with credentials
- Remove a member from a role for a service account
- Optional: defaults to the project associated with credentials
- Set a custom policy for a service account
- A policy object
- Optional: defaults to the project associated with credentials
IAMCredentials¶
The IAMCredentials
class allows you to work with IAM credentials, including JWT tokens, ID tokens, and custom tokens.
Initialization¶
from gcp_pilot.iam import IAMCredentials
iam_credentials = IAMCredentials() # (1)!
iam_credentials = IAMCredentials(impersonate_account="service-account@project-id.iam.gserviceaccount.com") # (2)!
- Initialize with default credentials
- Initialize with service account impersonation
Working with JWT Tokens¶
# Encode a JWT token (1)!
payload = {
"sub": "user@example.com",
"aud": "https://example.com",
"iat": datetime.now(tz=UTC).timestamp(),
"exp": (datetime.now(tz=UTC) + timedelta(hours=1)).timestamp(),
"custom_claim": "custom_value",
}
jwt_token = iam_credentials.encode_jwt(
payload=payload,
service_account_email="service-account@project-id.iam.gserviceaccount.com",
)
print(f"JWT Token: {jwt_token}")
decoded_token = IAMCredentials.decode_jwt( # (2)!
token=jwt_token,
issuer_email="service-account@project-id.iam.gserviceaccount.com",
audience="https://example.com",
verify=True, # (3)!
cache_certs=True, # (4)!
clock_skew_in_seconds=0, # (5)!
)
print(f"Decoded Token: {decoded_token}")
- Encode a JWT token
- Decode a JWT token
- Optional: if True, verifies the token signature
- Optional: if True, caches the public certificates
- Optional: allows for clock skew
Working with ID Tokens¶
id_token = iam_credentials.generate_id_token( # (1)!
audience="https://example.com",
service_account_email="service-account@project-id.iam.gserviceaccount.com", # (2)!
)
print(f"ID Token: {id_token}")
decoded_token = IAMCredentials.decode_id_token( # (3)!
token=id_token,
audience="https://example.com", # (4)!
)
print(f"Decoded Token: {decoded_token}")
- Generate an ID token
- Optional: defaults to the impersonated account
- Decode an ID token
- Optional: if provided, verifies the audience
Working with Custom Tokens¶
custom_token = iam_credentials.generate_custom_token( # (1)!
uid="user123", # (2)!
expires_in_seconds=3600, # (3)!
tenant_id="tenant123", # (4)!
auth_email="service-account@project-id.iam.gserviceaccount.com", # (5)!
claims={"premium_account": True}, # (6)!
)
print(f"Custom Token: {custom_token}")
decoded_token = IAMCredentials.decode_custom_token( # (7)!
token=custom_token,
issuer_email="service-account@project-id.iam.gserviceaccount.com",
verify=True, # (8)!
)
print(f"Decoded Token: {decoded_token}")
- Generate a custom token for Firebase Authentication
- Optional: defaults to a random UUID
- Optional: defaults to 12 hours
- Optional: for multi-tenancy
- Optional: defaults to the impersonated account
- Optional: custom claims
- Decode a custom token
- Optional: if True, verifies the token signature
Error Handling¶
The IAM classes handle common errors and convert them to more specific exceptions:
from gcp_pilot import exceptions
try:
iam.get_service_account(name="non-existent-account")
except exceptions.NotFound:
print("Service account not found")
try:
iam.create_service_account(name="existing-account", display_name="Existing Account", exists_ok=False)
except exceptions.AlreadyExists:
print("Service account already exists")
try:
iam_credentials.encode_jwt(payload={"exp": datetime.now(tz=UTC).timestamp() + 13 * 60 * 60}, service_account_email="service-account@project-id.iam.gserviceaccount.com")
except ValueError:
print("JWT tokens cannot be valid for more than 12 hours")
Working with Service Account Impersonation¶
Service account impersonation allows you to act as a service account without having its key file. This is a more secure approach than downloading and storing service account keys.
iam = IdentityAccessManager(impersonate_account="service-account@project-id.iam.gserviceaccount.com") # (1)!
service_account = iam.get_service_account(name="another-service-account") # (2)!
- Initialize with service account impersonation
- Now all operations will be performed as the impersonated service account
For more information on service account impersonation, see the Authentication documentation.
Common IAM Roles¶
Here are some common IAM roles that you might use with service accounts:
roles/iam.serviceAccountUser
: Allows a user to impersonate a service accountroles/iam.serviceAccountTokenCreator
: Allows a user to create tokens for a service accountroles/iam.serviceAccountKeyAdmin
: Allows a user to manage keys for a service accountroles/iam.serviceAccountAdmin
: Allows a user to create and manage service accounts
You can use these roles when binding members to service accounts:
policy = iam.bind_member( # (1)!
target_email="my-service-account@my-project.iam.gserviceaccount.com",
member_email="user@example.com",
role="roles/iam.serviceAccountUser",
)
- Grant the serviceAccountUser role to a user