diff --git a/core/modules/config/src/Tests/DefaultConfigTest.php b/core/modules/config/src/Tests/DefaultConfigTest.php
index 04b697b..265461b 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 0000000..15e0581
--- /dev/null
+++ b/core/modules/migrate/config/schema/migrate.data_types.schema.yml
@@ -0,0 +1,16 @@
+# 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'
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 0000000..00456ca
--- /dev/null
+++ b/core/modules/migrate/config/schema/migrate.destination.schema.yml
@@ -0,0 +1,13 @@
+# Schema for the migrate destination plugins.
+
+migrate.destination.*:
+  type: migrate_destination
+  label: 'Default destination'
+
+migrate.destination.config:
+  type: mapping
+  label: 'Config'
+  mapping:
+    config_name:
+      type: string
+      label: 'Configuration name'
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 0000000..6cf4847
--- /dev/null
+++ b/core/modules/migrate/config/schema/migrate.schema.yml
@@ -0,0 +1,37 @@
+# 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'
+    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 0000000..c748bac
--- /dev/null
+++ b/core/modules/migrate/config/schema/migrate.source.schema.yml
@@ -0,0 +1,64 @@
+# Schema for the migrate source plugins.
+
+migrate.source.*:
+  type: migrate_source
+  label: 'Default source'
+
+migrate.source.variable:
+  type: mapping
+  label: 'Variable'
+  mapping:
+    variables:
+      type: sequence
+      label: 'Variables'
+      sequence:
+        - type: string
+          label: 'Variable'
+
+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'
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 0000000..a0d2792
--- /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 0000000..b8f31aa
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateConfigSchemaBase.php
@@ -0,0 +1,144 @@
+<?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);
+    $this->schema = $typed_config->create($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);
+  }
+
+}
