diff --git a/core/modules/config/src/Tests/DefaultConfigTest.php b/core/modules/config/src/Tests/DefaultConfigTest.php
index 04b697b58df39844f776c9298f24c8145dee45ae..265461bd738cb540b0d97fe470521152a4d8529e 100644
--- a/core/modules/config/src/Tests/DefaultConfigTest.php
+++ b/core/modules/config/src/Tests/DefaultConfigTest.php
@@ -54,12 +54,6 @@ public function testDefaultConfig() {
     $default_config_storage = new TestInstallStorage();
 
     foreach ($default_config_storage->listAll() as $config_name) {
-      // @todo: remove once migration (https://drupal.org/node/2183957) schemas
-      // are in.
-      if (strpos($config_name, 'migrate.migration') === 0) {
-        continue;
-      }
-
       // Skip files provided by the config_schema_test module since that module
       // is explicitly for testing schema.
       if (strpos($config_name, 'config_schema_test') === 0) {
diff --git a/core/modules/migrate/config/schema/migrate.data_types.schema.yml b/core/modules/migrate/config/schema/migrate.data_types.schema.yml
new file mode 100644
index 0000000000000000000000000000000000000000..efdee08ca772c0e6288c731479f3eeb3f73337c9
--- /dev/null
+++ b/core/modules/migrate/config/schema/migrate.data_types.schema.yml
@@ -0,0 +1,20 @@
+# Basic data types for Migrate.
+
+migrate_plugin:
+  type: mapping
+  mapping:
+    plugin:
+      type: string
+      label: 'Plugin'
+
+migrate_destination:
+  type: migrate_plugin
+  label: 'Destination'
+
+migrate_source:
+  type: migrate_plugin
+  label: 'Source'
+
+migrate_load:
+  type: migrate_plugin
+  label: 'Load'
diff --git a/core/modules/migrate/config/schema/migrate.destination.schema.yml b/core/modules/migrate/config/schema/migrate.destination.schema.yml
new file mode 100644
index 0000000000000000000000000000000000000000..97cf48c3e716d90ad1396373bfe6b4c4b2be9dd0
--- /dev/null
+++ b/core/modules/migrate/config/schema/migrate.destination.schema.yml
@@ -0,0 +1,29 @@
+# Schema for the migrate destination plugins.
+
+migrate.destination.*:
+  type: migrate_destination
+  label: 'Default destination'
+
+migrate.destination.config:
+  type: migrate_destination
+  label: 'Config'
+  mapping:
+    config_name:
+      type: string
+      label: 'Configuration name'
+
+"migrate.destination.entity:user":
+  type: migrate_destination
+  label: 'User'
+  mapping:
+    md5_passwords:
+      type: boolean
+      label: 'Passwords'
+
+"migrate.destination.entity:file":
+  type: migrate_destination
+  label: 'Picture'
+  mapping:
+    source_path_property:
+      type: string
+      label: 'Source path'
diff --git a/core/modules/migrate/config/schema/migrate.load.schema.yml b/core/modules/migrate/config/schema/migrate.load.schema.yml
new file mode 100644
index 0000000000000000000000000000000000000000..aab94691cae6f6de59b41602189c4f6c50c52af2
--- /dev/null
+++ b/core/modules/migrate/config/schema/migrate.load.schema.yml
@@ -0,0 +1,21 @@
+# Schema for the migrate load plugins.
+
+migrate.load.*:
+  type: migrate_load
+  label: 'Default load'
+
+migrate.load.drupal_entity:
+  type: migrate_load
+  label: 'Default source'
+  mapping:
+    bundle_migration:
+      type: string
+      label: 'Bundle migration'
+
+migrate.load.d6_term_node:
+  type: migrate_load
+  label: 'Default source'
+  mapping:
+    bundle_migration:
+      type: string
+      label: 'Bundle migration'
diff --git a/core/modules/migrate/config/schema/migrate.schema.yml b/core/modules/migrate/config/schema/migrate.schema.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cdca049a7f1b8657e7cb3cc07007d4a7e6b998d1
--- /dev/null
+++ b/core/modules/migrate/config/schema/migrate.schema.yml
@@ -0,0 +1,40 @@
+# Schema for the configuration files of the Migrate module.
+
+migrate.migration.*:
+  type: mapping
+  label: 'Migration'
+  mapping:
+    id:
+      type: string
+      lable: 'ID'
+    label:
+      type: label
+      label: 'Label'
+    load:
+      type: migrate.load.[plugin]
+      label: 'Source'
+    source:
+      type: migrate.source.[plugin]
+      label: 'Source'
+    process:
+      type: ignore
+      label: 'Process'
+    destination:
+      type: migrate.destination.[plugin]
+      label: 'Destination'
+    migration_dependencies:
+      type: mapping
+      label: 'Dependencies'
+      mapping:
+        required:
+          type: sequence
+          label: 'Required dependencies'
+          sequence:
+            - type: string
+              label: 'Dependency'
+        optional:
+          type: sequence
+          label: 'Optional dependencies'
+          sequence:
+            - type: string
+              label: 'Dependency'
diff --git a/core/modules/migrate/config/schema/migrate.source.schema.yml b/core/modules/migrate/config/schema/migrate.source.schema.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b0ff9e76ca9c390410972084dfdc2519f4e0382e
--- /dev/null
+++ b/core/modules/migrate/config/schema/migrate.source.schema.yml
@@ -0,0 +1,388 @@
+# Schema for the migrate source plugins.
+
+migrate.source.*:
+  type: migrate_source
+  label: 'Default source'
+
+migrate.source.variable:
+  type: migrate_source
+  label: 'Variable'
+  mapping:
+    variables:
+      type: sequence
+      label: 'Variables'
+      sequence:
+        - type: string
+          label: 'Variable'
+    constants:
+      type: mapping
+      label: 'Constants'
+      mapping:
+        entity_type:
+          type: string
+          label: 'Entity type'
+        id:
+          type: string
+          label: 'ID'
+        label:
+          type: label
+          label: 'Label'
+        description:
+          type: text
+          label: 'Description'
+        path:
+          type: string
+          label: 'Path'
+        plugin:
+          type: string
+          label: 'Plugin'
+
+migrate.source.d6_comment:
+  type: migrate_source
+  label: 'Drupal 6 book'
+  mapping:
+    constants:
+      type: mapping
+      label: 'Constants'
+      mapping:
+        field_id:
+          type: string
+          label: 'Field ID'
+        entity_type:
+          type: string
+          label: 'Entity type'
+
+migrate.source.d6_comment_variable:
+  type: migrate_source
+  label: 'Drupal 6 book'
+  mapping:
+    constants:
+      type: mapping
+      label: 'Constants'
+      mapping:
+        entity_type:
+          type: string
+          label: 'Entity type'
+        field_name:
+          type: string
+          label: 'Entity type'
+        view_mode:
+          type: string
+          label: 'Entity type'
+        options:
+          type: sequence
+          label: 'Options'
+          sequence:
+            - type: string
+              label: 'Option'
+        type:
+          type: string
+          label: 'Type'
+        id:
+          type: string
+          label: 'ID'
+        name:
+          type: label
+          label: 'Name'
+
+migrate.source.d6_comment:
+  type: migrate_source
+  label: 'Drupal 6 comment'
+  mapping:
+    constants:
+      type: mapping
+      label: 'Constants'
+      mapping:
+        field_name:
+          type: string
+          label: 'Field name'
+        comment_type:
+          type: string
+          label: 'Comment type'
+        entity_type:
+          type: string
+          label: 'Entity type'
+
+migrate.source.d6_box:
+  type: migrate_source
+  label: 'Drupal 6 box'
+  mapping:
+    constants:
+      type: mapping
+      label: 'Constants'
+      mapping:
+        type:
+          type: string
+          label: 'Type'
+
+migrate.source.d6_taxonomy_vocabulary:
+  type: migrate_source
+  label: 'Drupal 6 field instance form display'
+  mapping:
+    constants:
+      type: migrate_entity_constant
+      label: 'Constants'
+
+migrate.source.d6_field_instance_per_form_display:
+  type: migrate_source
+  label: 'Drupal 6 field instance form display'
+  mapping:
+    constants:
+      type: migrate_entity_constant
+      label: 'Constants'
+
+migrate.source.d6_taxonomy_vocabulary_per_type:
+  type: migrate_source
+  label: 'Drupal 6 field instance form display'
+  mapping:
+    constants:
+      type: migrate_entity_constant
+      label: 'Constants'
+
+migrate.source.d6_taxonomy_vocabulary_per_type:
+  type: migrate_source
+  label: 'Drupal 6 field instance form display'
+  mapping:
+    constants:
+      type: migrate_entity_constant
+      label: 'Constants'
+
+migrate.source.d6_field:
+  type: migrate_source
+  label: 'Drupal 6 box'
+  mapping:
+    constants:
+      type: migrate_entity_constant
+      label: 'Constants'
+
+migrate.source.variable_multirow:
+  type: migrate_source
+  label: 'Drupal 6 box'
+  mapping:
+    variables:
+      type: sequence
+      label: 'Variables'
+      sequence:
+        - type: string
+          label: 'Variable'
+
+migrate.source.d6_comment_variable:
+  type: migrate_source
+  label: 'Drupal 6 comment variable'
+  mapping:
+    constants:
+      type: migrate_entity_constant
+      label: 'Constants'
+
+migrate.source.d6_contact_settings:
+  type: migrate_source
+  label: 'Drupal 6 contact settings'
+  mapping:
+    variables:
+      type: sequence
+      label: 'Variables'
+      sequence:
+        - type: string
+          label: 'Variable'
+
+migrate.source.d6_view_mode:
+  type: migrate_source
+  label: 'Drupal 6 view mode'
+  mapping:
+    constants:
+      type: mapping
+      label: 'Constants'
+      mapping:
+        targetEntityType:
+          type: string
+          label: 'Target entity type'
+        status:
+          type: boolean
+          label: 'Status'
+
+migrate.source.d6_profile_field:
+  type: migrate_source
+  label: 'Drupal 6 profile field'
+  mapping:
+    constants:
+      type: migrate_entity_constant
+      label: 'Constants'
+
+migrate.source.d6_field_formatter_settings:
+  type: migrate_source
+  label: 'Drupal 6 field formatter settings'
+  mapping:
+    constants:
+      type: migrate_entity_constant
+      label: 'Constants'
+
+migrate.source.d6_node_type:
+  type: migrate_source
+  label: 'Drupal 6 node type'
+  mapping:
+    constants:
+      type: mapping
+      label: 'Constants'
+      mapping:
+        preview:
+          type: integer
+          label: 'Preview'
+        create_body:
+          type: boolean
+          label: 'create body'
+
+migrate.source.d6_upload_instance:
+  type: migrate_source
+  label: 'Drupal 6 upload form display'
+  mapping:
+    constants:
+      type: migrate_entity_constant
+      label: 'Constants'
+
+migrate.source.d6_field_instance:
+  type: migrate_source
+  label: 'Drupal 6 field instance'
+  mapping:
+    constants:
+      type: migrate_entity_constant
+      label: 'Constants'
+
+migrate.source.d6_field_instance_per_view_mode:
+  type: migrate_source
+  label: 'Drupal 6 field formatter'
+  mapping:
+    constants:
+      type: migrate_entity_constant
+      label: 'Constants'
+
+migrate.source.empty:
+  type: migrate_source
+  label: 'Drupal 6 field formatter'
+  mapping:
+    provider:
+      type: string
+      label: 'Provider'
+    constants:
+      type: mapping
+      label: 'Constants'
+      mapping:
+        entity_type:
+          type: string
+          label: 'Entity type'
+        type:
+          type: string
+          label: 'Type'
+        name:
+          type: string
+          label: 'Name'
+        cardinality:
+          type: integer
+          label: 'Cardinality'
+        display_field:
+          type: boolean
+          label: 'Display field'
+
+migrate.source.d6_user_picture_file:
+  type: migrate_source
+  label: 'Drupal 6 user picure display'
+  mapping:
+    constants:
+      type: mapping
+      label: 'Constant'
+      mapping:
+        is_public:
+          type: boolean
+          label: 'Public'
+
+migrate.source.d6_user_picture_instance:
+  type: migrate_source
+  label: 'Drupal 6 user picure display'
+  mapping:
+    provider:
+      type: string
+      label: 'Provider'
+    constants:
+      type: migrate_entity_constant
+      label: 'Constants'
+
+migrate_entity_constant:
+  type: mapping
+  mapping:
+    entity_type:
+      type: string
+      label: 'Entity type'
+    bundle:
+      type: string
+      label: 'Bundle'
+    label:
+      type: label
+      label: 'Label'
+    id:
+      type: string
+      label: 'ID'
+    view_mode:
+      type: string
+      label: 'View mode'
+    form_mode:
+      type: string
+      label: 'Form mode'
+    field_name:
+      type: string
+      label: 'Field name'
+    empty:
+      type: sequence
+      label: 'Empty'
+      sequence:
+        - type: string
+          label: 'Empty'
+    name:
+      type: string
+      label: 'Name'
+    required:
+      type: boolean
+      label: 'Required'
+    type:
+      type: string
+      label: 'Type'
+    cardinality:
+      type: integer
+      label: 'Cardinality'
+    parent:
+      type: integer
+      label: 'Parent'
+    langcode:
+      type: string
+      label: 'Type'
+    third_party_settings:
+      type: sequence
+      label: 'Settings'
+      sequence:
+        - type: ignore
+          label: 'Settings'
+    settings:
+      type: sequence
+      label: 'Settings'
+      sequence:
+        - type: ignore
+          label: 'Settings'
+    options:
+      type: mapping
+      label: 'Options'
+      mapping:
+        label:
+          type: string
+          label: 'label'
+        type:
+          type: string
+          label: 'Type'
+        weight:
+          type: integer
+          label: 'Weight'
+        settings:
+          type: sequence
+          label: 'Settings'
+          sequence:
+            - type: string
+              label: 'Settings'
+
+
diff --git a/core/modules/migrate_drupal/config/install/migrate.migration.d6_contact_settings.yml b/core/modules/migrate_drupal/config/install/migrate.migration.d6_contact_settings.yml
index 65b0082419dae1ee5092c33295e079c4d905f58f..e45dde1e5b4fbe306d8f5f4b7671d36565ac4c49 100644
--- a/core/modules/migrate_drupal/config/install/migrate.migration.d6_contact_settings.yml
+++ b/core/modules/migrate_drupal/config/install/migrate.migration.d6_contact_settings.yml
@@ -15,5 +15,6 @@ process:
 destination:
   plugin: config
   config_name: contact.settings
-dependencies:
-  - d6_contact_category
+migration_dependencies:
+  required:
+    - d6_contact_category
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateActionConfigSchemaTest.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateActionConfigSchemaTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a0d27920b350c81b59643466ea48c6c278a1ea19
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateActionConfigSchemaTest.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateActionConfigSchemaTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+
+/**
+ * Tests the language config schema.
+ */
+class MigrateActionConfigSchemaTest extends MigrateConfigSchemaBase {
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('action');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate action configuration schema',
+      'description'  => 'Tests the configuration schema of action module',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $migration = entity_load('migration', 'd6_action_settings');
+    $dumps = array(
+      $this->getDumpDirectory() . '/Drupal6ActionSettings.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests migration of action variables to action.settings.yml.
+   */
+  public function testActionConfigSchema() {
+    $config_data = \Drupal::config('action.settings')->get();
+    $this->assertConfigSchema(\Drupal::service('config.typed'), 'action.settings', $config_data);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateConfigSchemaBase.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateConfigSchemaBase.php
new file mode 100644
index 0000000000000000000000000000000000000000..7af563f0a10f5aa985dbb8c9b0740494f4bbe8d1
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateConfigSchemaBase.php
@@ -0,0 +1,145 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\MigrateDrupalTestBase.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\Core\Config\Schema\ArrayElement;
+use Drupal\Core\Config\TypedConfigManagerInterface;
+use Drupal\Core\TypedData\Type\BooleanInterface;
+use Drupal\Core\TypedData\Type\StringInterface;
+use Drupal\Component\Utility\String;
+use Drupal\Core\Config\Schema\SchemaIncompleteException;
+use Drupal\Core\TypedData\PrimitiveInterface;
+use Drupal\Core\TypedData\Type\FloatInterface;
+use Drupal\Core\TypedData\Type\IntegerInterface;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Base class for Drupal migration tests.
+ */
+abstract class MigrateConfigSchemaBase extends MigrateDrupalTestBase {
+
+
+  /**
+   * The config schema wrapper object for the configuration object under test.
+   *
+   * @var \Drupal\Core\Config\Schema\Element
+   */
+  protected $schema;
+
+  /**
+   * The configuration object name under test.
+   *
+   * @var string
+   */
+  protected $configName;
+
+  /**
+   * Global state for whether the config has a valid schema.
+   *
+   * @var boolean
+   */
+  protected $configPass;
+
+  /**
+   * Asserts the TypedConfigManager has a valid schema for the configuration.
+   *
+   * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
+   *   The TypedConfigManager.
+   * @param string $config_name
+   *   The configuration name.
+   * @param array $config_data
+   *   The configuration data.
+   */
+  public function assertConfigSchema(TypedConfigManagerInterface $typed_config, $config_name, $config_data) {
+    $this->configName = $config_name;
+    if (!$typed_config->hasConfigSchema($config_name)) {
+      $this->fail(String::format('No schema for !config_name', array('!config_name' => $config_name)));
+      return;
+    }
+    $definition = $typed_config->getDefinition($config_name);
+    $data_definition = $typed_config->buildDataDefinition($definition, $config_data);
+    $this->schema = $typed_config->create($data_definition, $config_data);
+    $this->configPass = TRUE;
+    foreach ($config_data as $key => $value) {
+      $this->checkValue($key, $value);
+    }
+    if ($this->configPass) {
+      $this->pass(String::format('Schema found for !config_name and values comply with schema.', array('!config_name' => $config_name)));
+    }
+  }
+
+  /**
+   * Helper method to check data type.
+   *
+   * @param string $key
+   *   A string of configuration key.
+   * @param mixed $value
+   *   Value of given key.
+   *
+   * @return mixed
+   *   Returns mixed value.
+   */
+  protected function checkValue($key, $value) {
+    $element = FALSE;
+    try {
+      $element = $this->schema->get($key);
+    }
+    catch (SchemaIncompleteException $e) {
+      if (is_scalar($value) || $value === NULL) {
+        $this->fail("{$this->configName}:$key has no schema.");
+      }
+    }
+    // Do not check value if it is defined to be ignored.
+    if ($element && $element instanceof Ignore) {
+      return $value;
+    }
+
+    if (is_scalar($value) || $value === NULL) {
+      $success = FALSE;
+      $type = gettype($value);
+      if ($element instanceof PrimitiveInterface) {
+        $success =
+          ($type == 'integer' && $element instanceof IntegerInterface) ||
+          ($type == 'double' && $element instanceof FloatInterface) ||
+          ($type == 'boolean' && $element instanceof BooleanInterface) ||
+          ($type == 'string' && $element instanceof StringInterface) ||
+          // Null values are allowed for all types.
+          ($value === NULL);
+      }
+      $class = get_class($element);
+      if (!$success) {
+        $this->fail("{$this->configName}:$key has the wrong schema. Variable type is $type and schema class is $class.");
+      }
+    }
+    else {
+      if (!$element instanceof ArrayElement) {
+        $this->fail("Non-scalar {$this->configName}:$key is not defined as an array type (such as mapping or sequence).");
+      }
+
+      // Go on processing so we can get errors on all levels. Any non-scalar
+      // value must be an array so cast to an array.
+      if (!is_array($value)) {
+        $value = (array) $value;
+      }
+      // Recurse into any nested keys.
+      foreach ($value as $nested_value_key => $nested_value) {
+        $value[$nested_value_key] = $this->checkValue($key . '.' . $nested_value_key, $nested_value);
+      }
+    }
+    return $value;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function fail($message = NULL, $group = 'Other') {
+    $this->configPass = FALSE;
+    return parent::fail($message, $group);
+  }
+
+}