Migrating projects

This guide explains how to move a project between organizations or places within a resource hierarchy.

The project resource is the base-level organizing entity in a Google Cloud organization. Projects are created under organizations, and can be placed under folders or the organization resource itself, forming the resource hierarchy. You may need to migrate projects between organizations due to acquisitions, regulatory requirements, and separation between business units, among other things.

You can use the Resource Manager API to move projects across organizations or to another place in the resource hierarchy of its current organization. The Resource Manager API also lets you roll back the migration, moving the project back to its original place in the resource hierarchy.

Create a migration plan

The most important thing to consider during a project move is how the migration will impact the services running inside the project. The Resource Manager API treats the project resource and all services running underneath it as a single unit, meaning that no configuration changes will be applied inside the project.

While migration will not make direct configuration changes to the project, the change in the resource hierarchy is likely to have an impact on the function of the project and its running services. Inherited policies, such as Identity and Access Management or organization policies, will not move with the project during migration, only policies and service accounts that are attached directly to the resource. This may cause unintended behavior after the migration is complete.

Before moving your project, you should consider creating a migration plan to determine the readiness of both your organization and the projects you want to move. In this migration plan, take inventory of each of the services that your project is running, and any other services that may be impacted by the move, or by the resource hierarchy in the destination for your project.

Inventory overview

Use Cloud Asset Inventory to create an overview of resources in use, including Identity and Access Management policies. You can use this overview to help outline your migration plan.

You can also use the open source Dataflow-job to transfer this data into BigQuery. This will allow you to query the data using SQL, which is easier to read compared to interpreting JSON-formatted data.

Policy verification

When you migrate your project, it will no longer inherit the policies from its current place in the resource hierarchy, and will be subject to the effective policy evaluation at its destination. We recommend making sure that the effective policies at the project's destination match as much as possible the policies that the project had in its source location.

Any policy that is applied directly to the project will still be attached after the migration is complete. Applying policies directly to the project is a good way to verify that the correct policies are applied from the moment the move is complete.

Identity and Access Management policies and organization policies are inherited through the resource hierarchy, and can block a service from functioning if not set properly. Determine the effective policy at the project's destination in your resource hierarchy to ensure the policy aligns with your governance objectives.

Preview features

You can enable preview features on organizations, folders, or projects. If you have enabled an alpha or beta feature on the project to be moved, this feature should continue to function after the migration. If the preview feature is private and not allowlisted for the destination organization, you will not be able to make any configuration changes after the move is complete.

Rollback plan

If you discover that something is not working on any of the projects you have migrated, you can move them back to their original location. In order to do that, you need to have the necessary IAM permissions and set the required organization policies so that you can run the project migration in reverse.

For a list of permissions required, see Assign permissions. For the organization policies you need to configure to allow a project migration, see Configure organization policies.

Dedicated import and export folders

Policy inheritance can cause unintended effects when you are migrating a project, both in the source and destination organizations. You can mitigate this risk by creating specific folders to hold only projects for export and import, and ensuring that the same policies are inherited by the folders in both organizations. You can also set permissions on these folders that will be inherited to the projects moved within them, helping to accelerate the project migration process.

When planning a migration, consider setting up a dedicated source folder first. To do this, create a folder for each organization to which you plan to export projects. Then, set an organization policy on these folders, each with the constraints/resourcemanager.allowedExportDestinations constraint set to the single organization to which you want to export projects.

For example, you could set up Export to Marketing Org and Export to Sales Org folders, each with appropriate organization policy constraints set.

Similarly, set up dedicated import folders in the destination organization, one for each organization from which you want to import projects. To do this, create a folder for each organization from which you plan to import projects. Then, set an organization policy on these folders, each with the constraints/resourcemanager.allowedImportSources constraint set to the single organization from which you want to import projects.

For example, you could set up Import from Marketing Org and Import from App Development Org folders, each with appropriate organization policy constraints set.

On each of the import and export folders, assign the person who will be moving the projects the roles/resourcemanager.projectMover role. This role will be inherited by any projects that are contained within these folders, giving the user the ability to perform the move operations on any project that is moved into those folders.

After you have completed your project migration, you should remove these dedicated folders.

For information about setting organization policies, see Configure organization policies.

Assign permissions

You need the following permissions to move a project between organizations.

To gain these permissions, ask your administrator to grant the suggested role at the appropriate level of the resource hierarchy.

Project move permissions

On the project resource that you want to move and its parent resource, you need the Project Mover role (roles/resourcemanager.projectMover), or another role that includes the following permissions for the v1 Resource Manager API:

  • Permission required for the resource you're moving:

    • resourcemanager.projects.update
  • Permission required for the parent resource:

    • resourcemanager.projects.move

On the destination resource, the permission you need depends on the resource to which you are moving the project.

  • If the destination resource is a folder, you need the Project Mover role (roles/resourcemanager.projectMover), or another role that includes the resourcemanager.projects.move permission.

  • If the destination resource is an organization, you need the Project Creator role (roles/resourcemanager.projectCreator), or another role that includes the resourcemanager.projects.create permissions.

Organization policy permissions

On the source and destination organizations, you must have the roles/orgpolicy.policyAdmin role, which grants permission to create and manage organization policies.

Configure organization policies

To move a project resource to a new organization, you must first apply an organization policy that will define the organizations to which the project can be moved. You must also set an organization policy in the destination that defines the organizations from which projects can be imported.

On the parent resource to the project you want to move, set an organization policy that includes the constraints/resourcemanager.allowedExportDestinations constraint. This will define the target destination as a valid location to which you can migrate the project.

On the destination resource, set an organization policy that includes the constraints/resourcemanager.allowedImportSources constraint. This will define the source as a valid location from which you can migrate your project.

For example, say you had a project my-test-project that existed under an organization with the ID 12345678901, and you wanted to move it to a new organization for your secondary business unit, with the ID 45678901234.

You would set an organization policy on organizations/12345678901with the constraints/resourcemanager.allowedExportDestinations constraint enforced and under:organizations/45678901234 set as an allowed_value.

Then, set an organization policy on organizations/45678901234 with the constraints/resourcemanager.allowedImportSources constraint enforced and under:organizations/12345678901 set as an allowed_value.

Once these organization policies are enforced, you will be able to move my-test-project from organizations/12345678901 to organizations/45678901234, assuming you have the permissions noted in Assign permissions.

Perform the migration

If you have the appropriate IAM permissions and the required organization policies are enforced, you can use the Resource Manager API to move a project resource.

gcloud

To migrate a project under an organization, run the following command:

gcloud alpha projects move PROJECT_ID /
    --organization ORGANIZATION_ID

You can also specify a folder as the target resource, with the following command:

gcloud alpha projects move PROJECT_ID /
    --folder FOLDER_ID

Where:

  • PROJECT_ID is the ID or number of the project you wish to migrate.
  • ORGANIZATION_ID is the ID of the organization to which you want to move the project. You can only specify one target, either an organization or a folder.
  • FOLDER_ID is the ID of the folder to which you want to move the project. You can only specify one target, either a folder or an organization.

API

Using the v1 Resource Manager API, you can move a project by setting its parent field to the ID of the destination resource.

To migrate a project=:

  • Get the project object using projects.get() method.
  • Set its parent field to the organization ID of the organization, or the folder ID of the folder to which you are moving it.
  • Update the project object using projects.update() method.

The following code snippet demonstrates the steps above:

    project = crm.projects().get(projectId=flags.projectId).execute()
    project['parent'] = {
        'type': 'organization',
        'id': flags.organizationId
    }

    project = crm.projects().update(
    projectId=flags.projectId, body=project).execute()

Roll back a migration

If you have mistakenly moved a project, you can roll back the operation by performing the move again, with the old source as the new destination, and the old destination as the new source. You must have the necessary IAM permissions and organization policies enforced to allow this as if this were an entirely new migration.

Handling special cases

Shared VPC

Shared VPC projects can be migrated following certain conditions. First, a user with the roles/orgpolicy.policyAdmin role in the source organization must set an organization policy containing the constraints/resourcemanager.allowEnabledServicesForExport constraint on the parent of the project to be exported. This constraint should list SHARED_VPC as an allowed_value.

The Shared VPC host project must be migrated first, followed by all of its service projects. If you move the host project, you can move it back to the source organization, but once you begin moving the service projects, you must move all of them before you can move the host project again.

Custom Identity and Access Management roles

Custom Identity and Access Management roles can be created at the organization level to provide granular control of access to resources, but they are only valid in the organization in which they are created. If you try to move a project that contains an IAM policy binding of a user to an organization-level custom IAM role, the move will fail with a failed precondition error, explaining that the role in question does not exist in the destination organization.

To list all custom IAM roles at the level of your organization, run the following gcloud command-line tool command:

gcloud iam roles list --organization ORGANIZATION_ID

Where the ORGANIZATION_ID is the organization ID for which you want to list roles. For information on finding your organization ID, see Creating and managing organizations.

To get information on a custom Identity and Access Management role in your organization, run the following gcloud command-line tool command:

gcloud iam roles describe --organization ORGANIZATION_ID \
    ROLE_ID

Where:

  • ORGANIZATION_ID is the organization ID of the role's parent organization.

  • ROLE_ID is the name of the role you want to describe.

To work around the failed precondition error, you should create equivalent project-level custom roles for each of the organization-level custom roles that the project inherits. Then, remove the IAM role bindings that reference the organization-level custom roles.

Once the project has been migrated, you can update the IAM policies to use the organization-level custom roles in the destination organization.

For more information about custom roles, see Creating and managing custom roles.

Bucket Lock

Cloud Storage Bucket Lock allows you to configure a data retention policy on a Cloud Storage bucket that governs how long objects in the bucket must be retained. The bucket lock is protected using a lien to prevent accidentally deleting the project.

The retention policy and lien are kept with the project during a migration, but you should be aware if you are moving a project with a bucket lock enforced, and prevent accidental moves.

VPC Service Controls security perimeters

VPC Service Controls allows users to set up a project-based security perimeter around their Google Cloud services to mitigate data exfiltration risks. You cannot migrate a project that is protected by a VPC Service Controls security perimeter.

To remove a project from a security perimeter, see Managing service perimeters. Projects in VPC Service Controls perimeters may not be blocked from being moved across organizations for up to a day after a perimeter has been created or updated. It may take several hours for the project to be movable after it has been removed from the service perimeter.

CDN Interconnect

We recommend migrating projects with CDN Interconnect objects and projects with VLAN attachments to these CDN Interconnect objects together. While projects with CDN Interconnect objects or VLAN attachments connected to them can be migrated and will function between organizations, you will not be able to create new VLAN attachments across the organization split.

Configuration changes made to a project in one organization that has a CDN Interconnect object attached or a VLAN attachment to the CDN Interconnect object may not propagate to the other, so we recommend not leaving such projects split across organizations for very long if possible.

Assured Workloads

You cannot move an Assured Workloads project between organizations. Any attempt to do so will be programmatically blocked.

Cross-project service accounts

If you are moving a project that has a cross-project service account attached to it, that service account will still function in the destination organization. That project will continue to work with the attached service account even if there is an organization policy that restricts the domain of that project.

If you are moving a project that owns a cross-project service account attached to another project in the source organization, the service account will still function in the destination organization. However, you will not be able to use the service account on any resources that have a domain restriction organization policy applied to them that restricts them to the source organization's domain.

For example, assume you have project-A, in organizations/12345678901. This project has serviceAccount-1 attached to it, which is set up as a cross-project service account. project-B and project-C, also in organizations/12345678901, use serviceAccount-1 as well.

You have applied an organization policy with the domain restriction constraint to project-C, which only allows it to access the domain of organizations/12345678901.

If you add serviceAccount-1 to the IAM binding for project-C, and then move project-A to organizations/45678901234, the service account will function.

If you move project-A to organizations/45678901234, and then try to add serviceAccount-1 to the IAM binding for project-C, the binding will fail as it violates the domain restriction constraint.

Support cases

If you move a project that has an open support case, you need to reach out to your Google Support contact to let them know the migration has occurred. Any projects that have an open support case with Google will not be able to view those support cases until Google Support updates the case metadata to point to the new organization.