This guide explains how to move a project between organization resources or places within a resource hierarchy.
The project resource is the base-level organizing entity in a Google Cloud organization resource. Projects are created under organization resources, and can be placed under folders or the organization resource itself, forming the resource hierarchy. You may need to migrate projects between organization resources due to acquisitions, regulatory requirements, and separation between business units, among other things.
You can use the Resource Manager API to move projects across organization resources or to another place in the resource hierarchy of its current organization resource. 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 the 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.
Moving your project might also result in organization policy violations, depending on the destination organization resource's organization policies.
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 Cloud Asset Inventory 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. For information about exporting this data, see Exporting to BigQuery.
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.
Manage encrypted keys
You should verify if your project has a customer-managed encrypted key or other
Cloud Key Management Service enabled on it. Cryptographic keys are owned by the project, and a
user with owner
access to that project will therefore be able to manage and
perform cryptographic operations on keys in Cloud KMS in that
project.
For more information, see Separation of duties.
Preview features
You can enable preview features on organization, folder, or project resources. 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 resource, 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 organization resources. 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 organization resources. 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 resource 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 resource 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
resource, one for each organization resource from which you want to import
projects. To do this, create a folder for each organization resource 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 resource 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 organization resources.
To gain these permissions, ask your administrator to grant the suggested role at the appropriate level of the resource hierarchy.
Project move permissions
To move a project, you need the following roles on the project, its parent resource, and the destination resource:
- Project IAM Admin (
roles/resourcemanager.projectIamAdmin
) on the project that you want to move - Project Mover (
roles/resourcemanager.projectMover
) on the project's parent resource - If the destination resource is a folder: Project Mover
(
roles/resourcemanager.projectMover
) on the destination resource - If the destination resource is an organization: Project Creator
(
roles/resourcemanager.projectCreator
) on the destination resource
These roles give you the following required permissions:
Required permissions
-
resourcemanager.projects.getIamPolicy
on the project you want to move -
resourcemanager.projects.update
on the project you want to move -
resourcemanager.projects.move
on the project's parent resource -
If the destination resource is a folder:
resourcemanager.projects.move
on the destination resource -
If the destination resource is an organization:
resourcemanager.projects.create
on the destination resource
You can also gain these permissions with a custom role, or other predefined roles.
Organization policy permissions
On the source and destination organization resources, the user setting the
organization policies must have the roles/orgpolicy.policyAdmin
role, which
grants permission to create and manage organization policies.
Billing account permissions
Cloud Billing accounts can be used across organization resources. Moving a project from one organization resource to another won't impact billing, and charges will continue against the old billing account. However, organization resource moves often also include a requirement to move to a new billing account.
To get the permissions that you need to change the project's billing account, ask your administrator to grant you the following IAM roles:
- Billing Account User (
roles/billing.user
) on the destination billing account - Project billing manager (
roles/billing.projectManager
) on the project
For more information about granting roles, see Manage access.
These predefined roles contain the permissions required to change the project's billing account. To see the exact permissions that are required, expand the Required permissions section:
Required permissions
-
billing. resourceAssociations.create
on the destination billing account -
resourcemanager.projects.createBillingAssignment
on the project -
resourcemanager.projects.deleteBillingAssignment
on the project
You might also be able to get these permissions with custom roles or other predefined roles.
Configure organization policies
To move a project resource to a new organization resource, you must first apply an organization policy that will define the organization resources to which the project can be moved. You must also set an organization policy in the destination that defines the organization resources 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 resource with the ID 12345678901
, and you wanted to move it to a
new organization resource for your secondary business unit, with the ID
45678901234
.
You would set an organization policy on organizations/12345678901
with 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.
Change the billing account for a project
Cloud Billing accounts can be used across organization resources. Moving a project from one organization resource to another won't impact billing, and charges will continue against the old billing account. However, organization resource moves often also include a requirement to move to a new billing account.
To change the billing account, do the following:
- Go to the Billing page in the Google Cloud console.
Go to the Billing page - Click the name of the billing account you want to change.
- Under Projects linked to this billing account, find the name of the Project to move and then click the menu button to the right.
- Click Change billing, and then select the new billing account.
- Click Set account.
Charges already incurred that have not yet been reported in the transaction history will be billed to the former billing account. This can include charges from up to two days prior to when the project was moved.
Move a billing account between organization resources
A billing account can be moved from one organization resource to another, although this isn't often a necessary step. Most existing organization resources will already have a billing account that should be used instead. If you need to migrate an existing billing account:
- Get the
roles/billing.admin
role on the source and destination organization resources. - Go to the Billing page in the Google Cloud console.
Go to the Billing page - Click on the name of the billing account you want to move.
- At the top of the Account Management page, click Change organization.
- Select the destination organization resource, and then click Ok.
The billing account is now associated with the specified organization resource.
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 to another organization resource, run the following command:
gcloud beta projects move PROJECT_ID \ --organization ORGANIZATION_ID
You can also specify a folder as the target resource, with the following command:
gcloud beta 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 resource to which you want to move the project. You can only specify one target, either an organization resource 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 resource.
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 usingprojects.get()
method. - Set its
parent
field to the organization resource ID of the organization resource, or the folder ID of the folder to which you are moving it. - Update the
project
object usingprojects.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
Migrating projects with no organization resource
You can migrate a project that is not associated with an organization resource into an organization resource. However, you can't change it back to No organization using this process. If you have a project that is associated with your organization resource and you want to revert it to No organization, reach out to your Support representative for assistance.
The process of migrating a project not associated with an organization resource is similar to the process for migrating a project between organization resources, but does not require all of the steps involved in the migration plan. To migrate a project into an organization resource, you should follow these steps:
Verify the impact on this project of the policies it will inherit.
Create a dedicated import folder in the destination organization resource, if desired.
Assign Identity and Access Management permissions for the project and the destination parent as detailed in Assign permissions.
Determine if you need to change the billing account.
Then, you can perform the migration.
Console
To migrate a project into an organization resource:
Open the IAM & admin > Settings page in the Google Cloud console.
Select the Project picker at the top of the page.
From the Organization picker, select No Organization. If you are not associated with any organization resource, the Organization picker will not appear, and you can skip this step.
Select the project you want to migrate.
At the top of the page, click Migrate.
On the Organization drop-down list, select the organization resource you want to migrate your project to.
gcloud
To migrate a project into an organization resource, run the following command:
gcloud beta projects move PROJECT_ID \ --organization ORGANIZATION_ID
Where:
- PROJECT_ID is the ID of the project you wish to move into the organization resource.
- ORGANIZATION_ID is the ID of the organization resource to which you wish to move the project.
API
Using the Resource Manager API, you can move a project into the organization
resource by setting its parent
field to the organization resource ID of
the organization resource.
To migrate a project into the organization resource:
- Get the
project
object usingprojects.get()
method. - Set its
parent
field to the organization resource ID of the organization resource. - Update the
project
object usingprojects.update()
method.
You can't change the parent
field after you set it.
The following code snippet demonstrates the steps above:
project = crm.projects().get(projectId=flags.projectId).execute()
project['parent'] = {
'type': 'organization',
'id': flags.organizationId
}
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. We recommend that you match the firewall rules between the organizations at the source and target locations, which should minimize potential issues and avoid any downtime for the projects and network during the migration. We do not offer guarantees about the healthiness of your network if you leave some service projects in the source organization indefinitely while migrating others.
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 resource 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 resource.
To list all custom IAM roles at the level of your organization resource, run the following Google Cloud CLI command:
gcloud iam roles list --organization ORGANIZATION_ID
Where the ORGANIZATION_ID
is the organization resource
ID for which you want to list roles. For information on finding your
organization resource ID, see Creating and managing organization resources.
To get information on a custom Identity and Access Management role in your organization resource, run the following Google Cloud CLI command:
gcloud iam roles describe --organization ORGANIZATION_ID \ ROLE_ID
Where:
ORGANIZATION_ID
is the organization resource ID of the role's parent organization resource.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 resource.
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 organization resources 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.
Dedicated Interconnect
We recommend migrating projects with Dedicated Interconnect objects and projects with VLAN attachments to these Dedicated Interconnect objects together. While projects with Dedicated Interconnect objects or VLAN attachments connected to them can be migrated and will function between organization resources, you will not be able to create new VLAN attachments across the organization resource split.
Configuration changes made to a project in one organization resource that has a Dedicated Interconnect object attached or a VLAN attachment to the Dedicated Interconnect object may not propagate to the other, so we recommend not leaving such projects split across organization resources for very long if possible.
Partner Interconnect
There are no special considerations needed when migrating projects with Partner Interconnect.
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 resource. 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 resource, the service account will still function in the destination organization resource. 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 resource'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 resource.
OAuth consent screen
If your project is configured to use an Internal OAuth consent screen and you migrate it to another organization resource, only members of the destination organization resource can authorize requests. It may take up to 24 hours for this behavior to take effect. Until then, members of the source organization resource an authorize requests.
The steps below explain how to ensure members of your source organization resource do not lose access during migration. Consider creating new users in your destination organization resource for organization resource members so that you do not need to change the OAuth consent screen configuration.
To avoid loss of access for members of the source organization resource:
Update the OAuth consent screen to be external instead of internal.
Apps that are marked internal and use sensitive data do not need to apply for app verification. If the app uses sensitive data, then when the consent screen is updated to external, the users of the source organization resource will see an unverified app screen before the authorization screen. To avoid this, apply for app verification for the use of sensitive or restricted scopes.
OS Login
If OS Login is enabled in
your source project, assign the roles/compute.osLoginExternalUser
IAM role to principals that can access the source project, in the
destination organization resource to avoid those principals losing access.
Attaching service accounts to resources
For most Google Cloud services, users need the iam.serviceAccounts.actAs
permission on a service account to attach that service account to a
resource. However, in the past, to ease onboarding certain services allowed
users to attach service accounts to resources even if the users didn't
have permission to impersonate the service accounts. This is documented
here.
If a customer's source organization resource has the legacy behavior (service
accounts attachment is possible without the normal role grant) and the
destination organization resource does not, grant roles/iam.serviceAccountUser
to users that attach these service accounts to resources. For information about
impersonating service accounts, see
Impersonating service accounts.
To see if your organization resource has the legacy behavior, do the following:
In the Google Cloud console, go to the Organization policies page.
From the project selector at the top of the page, choose the organization resource you want to check for legacy status.
In the filter box at the top of the list of organization policies, enter
constraints/appengine.enforceServiceAccountActAsCheck
.If the
appengine.enforceServiceAccountActAsCheck
organization policy appears in the list, the organization resource has the legacy behavior.Repeat steps 3 and 4 for each of the following organization policy constraints:
appengine.enforceServiceAccountActAsCheck
dataflow.enforceComputeDefaultServiceAccountCheck
dataproc.enforceComputeDefaultServiceAccountCheck
composer.enforceServiceAccountActAsCheck
If any of these organization policy constraints appear, your organization resource uses the legacy behavior.
If the source organization resource has the legacy behavior and the destination does not, grant the roles as mentioned above. If both the source and destination organization resources have the legacy behavior, no action is required, but consider enforcing the policy to prevent unintended impersonation.
Migrating projects with Analytics Hub
If you migrate the project that is using Analytics Hub to a different organization resource, you might encounter some error. To resolve any errors, contact support.
Migrating projects with Backup and DR service
Any project that is using Backup and DR service should not be migrated to a different organization.