Migrating a team's AI operations—encompassing everything from model training pipelines and vector databases to prompt engineering playgrounds and inference endpoints—to a new platform introduces a significant and often underestimated threat surface. The most common post-migration failures I've consulted on are not technical, but rather permissions-based: critical jobs cease because service accounts lack access, sensitive data becomes exposed to overly broad groups, or compliance auditors flag a toxic combination of inherited roles. A rigorous pre-migration permissions audit is non-negotiable, and it must go far beyond a simple inventory of users and groups.
The core principle is to map not just *who* has access, but *how* that access is granted within the source platform's specific identity and access management (IAM) fabric. You are translating an entire authorization model, not just user lists. Start by categorizing your AI assets and the access patterns.
**1. Asset Inventory & Principal Mapping**
First, enumerate the resources. This is more than just "the ML project." List:
* The primary compute resources (e.g., dedicated training clusters, inference endpoints, batch processing queues).
* Data sources and sinks (object storage buckets, feature stores, vector databases, data lakes).
* Orchestration controllers (pipelines, workflow managers).
* Supporting services (model registries, experiment trackers, secret managers).
For each, identify the *principals*: human users, service accounts, machine identities, and groups/roles. The critical task is to document the *granting mechanism*. For example:
```bash
# Example: GCP gcloud command to list IAM policy for a BigQuery dataset
gcloud beta bigquery datasets get-iam-policy project:dataset
--format=json | jq '.bindings[] | {role: .role, members: .members}'
```
This reveals if access is direct, via group membership, via a custom role, or inherited from a parent resource (a major source of scope creep).
**2. Analyzing Effective Permissions & Intent**
A list of bindings is raw data. You must analyze *effective permissions* to understand intent. A service account might have the `roles/editor` role on a project, granting broad permissions, but it may only need `roles/storage.objectViewer` on one bucket and `roles/aiplatform.user` for model deployment. The goal is to move from overly permissive, inherited roles to minimal, purpose-built permissions on the target platform. Key questions:
* Is this principal used for human interactive access or machine automation?
* Does the current role align with the principle of least privilege for its *proven* usage patterns? (Check logs).
* Are there toxic combinations where a principal has permissions across both data sources and model deployment that could lead to data exfiltration or model poisoning?
**3. Establishing a Translation Matrix**
Now, design a translation matrix from source platform roles to target platform roles. This is rarely 1:1. You must understand the semantic differences. For instance, a "Contributor" role in Azure ML Studio does not map cleanly to an AWS IAM policy; you must decompose it into specific S3, SageMaker, and EC2 permissions. Create a spreadsheet mapping:
* Source Principal
* Source Asset
* Source Role/Permissions
* **Justification & Usage Pattern** (from logs or team lead confirmation)
* Proposed Target Platform Role
* **Permission Gap Analysis** (what's missing, what's overly permissive)
**4. Validation Dry-Run & Cutover Strategy**
Before any live migration, use the target platform's policy simulation tools (like AWS IAM Policy Simulator, Azure Policy Tester, GCP Policy Troubleshooter) to validate your new permissions against recorded access patterns. Create the new service accounts and groups in the target platform and apply the translated policies. Then, run a dry-run of your critical AI pipelines using these new identities *against non-production resources* to catch failures.
Finally, plan the cutover. Permissions migration should precede data and pipeline migration. For a period, you may need to maintain both sets of credentials, switching over component by component. Document every change meticulously; this audit will serve as your authoritative baseline for the new environment and is invaluable for future security reviews. The time invested here directly correlates with the stability and security of your AI operations post-migration.
Plan the exit before entry.
Your emphasis on mapping the *how* of access, not just the *who*, is exactly right. Many teams produce a simple CSV export of user-to-role assignments and consider the audit complete. The critical failure mode they miss is the translation of implicit, platform-specific authorizations.
For example, in a source platform, a "Project Editor" role might implicitly grant write access to a specific cloud storage bucket via a naming convention and a broad, pre-existing bucket-level policy. That's a toxic combination of inherited roles. The target platform's equivalent "Editor" role likely has no such implicit bucket access. The post-migration breakage isn't a missing user, it's a missing side-channel permission. Your asset inventory must therefore include these dependent resources and, crucially, the *effective* access path for each principal, which requires analyzing policy inheritance trees and resource-level ACLs, not just the assigned roles.
Without this, you'll have a perfect list of users and a non-functional pipeline.
Data doesn't lie, but folks sometimes do.
Absolutely. You're hitting the nail on the head with asset inventory and *access patterns*. Mapping the static list is step zero. The real challenge is capturing those dynamic, session-based permissions that are crucial for AI workflows.
For example, a training job's service account might only need write access to a specific GCS prefix for model checkpoints *during the job's execution*. In GCP, that could be modeled with a temporary, conditional IAM binding. If your audit only captures the service account's persistent roles, you'll miss this temporal dependency and the job will fail post-migration when it tries to write.
Have you considered using policy-as-code tools like OPA/Rego or terraform's `iam` modules to define these patterns declaratively *before* the move? It forces you to model the "how" explicitly. You could even generate some of your audit findings by diffing the current live state against that declared policy.
YAML is not a programming language, but I treat it like one.
This is a great point, but doesn't it also go the other way? A source platform might have more restrictive defaults, like blocking public access to a new storage bucket by default. If your team's workflow implicitly depends on a public-read bucket and you only map the explicit IAM bindings, you'll migrate the binding but not the public setting, and break something downstream that fetches from it without credentials.
How do you track those platform-specific *deny* defaults?
Thanks for posting this guide, it's really helpful. That point about translating the whole authorization model, not just user lists, hits home.
We learned this the hard way when our automated data prep jobs failed after a cloud move. The service account had the right "bigquery job user" role in the new system, but we missed how it was also implicitly a "storage object viewer" on the source side because of a project-level inheritance setting. The job just silently couldn't read its own source data.
Do you have any tips for teasing out those implicit, inherited permissions systematically? Our IAM export tools seem to only show the direct bindings.