diff --git a/deploy.permissions.yml b/deploy.permissions.yml
index fd4d44b..61336db 100644
--- a/deploy.permissions.yml
+++ b/deploy.permissions.yml
@@ -1,5 +1,8 @@
 administer deployments:
   title: 'Administer deployments'
-
+deploy to any workspace:
+  title: 'Deploy to any workspace'
+deploy to own workspace:
+  title: 'Deploy to own workspace'
 permission_callbacks:
   - \Drupal\deploy\DeployPermissions::workspacePointerPermissions
diff --git a/src/ReplicationAccessControlHandler.php b/src/ReplicationAccessControlHandler.php
index 1a00894..5a0bc48 100644
--- a/src/ReplicationAccessControlHandler.php
+++ b/src/ReplicationAccessControlHandler.php
@@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Session\AccountInterface;
+use Drupal\multiversion\Entity\Workspace;
 use Drupal\multiversion\Workspace\WorkspaceManagerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -67,11 +68,33 @@ class ReplicationAccessControlHandler extends EntityAccessControlHandler impleme
     $active_workspace = $this->workspaceManager->getActiveWorkspace();
     $upstream_workspace_pointer = $active_workspace->upstream->entity;
 
-    // When no upstream workspace pointer is set or when the user doesn't have
-    // the permissions to deploy to the upstream, the access is forbidden.
-    if (!$upstream_workspace_pointer || !$account->hasPermission('Deploy to ' . $upstream_workspace_pointer->label())) {
-      $access = AccessResult::forbidden();
+    // When no upstream workspace pointer is set the access is forbidden.
+    if (!$upstream_workspace_pointer) {
+      return AccessResult::forbidden();
+    }
+
+    // The 'deploy to any workspace' permission will always allow the user to
+    // create replication entities and perform deployments.
+    if ($account->hasPermission('deploy to any workspace')) {
+      return AccessResult::allowed();
+    }
+
+    // Load just the ID and workspace separately to allow for remote workspace
+    // pointers which won't have the workspace_pointer field set.
+    $upstream_workspace_id = $upstream_workspace_pointer->workspace_pointer->target_id;
+    $upstream_workspace = Workspace::load($upstream_workspace_id);
+    // When the upstream workspace is set, the owner matches the account, and
+    // the user has the correct permission then allow access.
+    if ($upstream_workspace && $upstream_workspace->getOwnerId() == $account->id() && $account->hasPermission('deploy to own workspace')) {
+      return AccessResult::allowed();
     }
+
+    // When the user doesn't have permissions to deploy to the upstream the
+    // access is forbidden.
+    if (!$account->hasPermission('Deploy to ' . $upstream_workspace_pointer->label())) {
+      return AccessResult::forbidden();
+    }
+
     return $access;
   }
 
diff --git a/tests/src/Functional/DeploymentAccessTest.php b/tests/src/Functional/DeploymentAccessTest.php
index 5ca9193..d10acdb 100644
--- a/tests/src/Functional/DeploymentAccessTest.php
+++ b/tests/src/Functional/DeploymentAccessTest.php
@@ -59,7 +59,46 @@ class DeploymentAccessTest extends BrowserTestBase {
     $web_assert->linkExists('Stage');
     $web_assert->linkExists('Deploy');
     $this->drupalGet('/admin/structure/deployment/add');
-    $web_assert->statusCodeEquals('200');
+    $web_assert->pageTextContains('Deploy Stage to Live');
+
+    // Create a new workspace.
+    $this->drupalPostForm('/admin/structure/workspace/add', [
+      'machine_name' => 'my_workspace',
+      'label' => 'My Workspace',
+      'upstream' => 2,
+    ], 'Save');
+
+    // Update stage to deploy to my_workspace.
+    $this->drupalPostForm('/admin/structure/workspace/2/edit', [
+      'upstream' => 3,
+    ], 'Save');
+
+    // The user shouldn't be able to deploy to workspaces they created.
+    $this->drupalGet('/admin/structure/deployment/add');
+    $web_assert->statusCodeEquals('403');
+
+    // Give the user access to deploy to workspaces they created.
+    $test_user_roles = $test_user->getRoles();
+    $this->grantPermissions(Role::load(reset($test_user_roles)), ['deploy to own workspace']);
+
+    // The user should now have access to the deployment form.
+    $this->drupalGet('/admin/structure/deployment/add');
+    $web_assert->pageTextContains('Deploy Stage to My Workspace');
+
+    // Switch to the my_workspace workspace.
+    $this->drupalPostForm('/admin/structure/workspace/3/activate', [], 'Activate');
+
+    // The user doesn't have permission to deploy to stage.
+    $this->drupalGet('/admin/structure/deployment/add');
+    $web_assert->statusCodeEquals('403');
+
+    // Give the user access to deploy to any workspace.
+    $test_user_roles = $test_user->getRoles();
+    $this->grantPermissions(Role::load(reset($test_user_roles)), ['deploy to any workspace']);
+
+    // The user should now have access to the deployment form.
+    $this->drupalGet('/admin/structure/deployment/add');
+    $web_assert->pageTextContains('Deploy My Workspace to Stage');
   }
 
 }
