diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml
index 95311ad..fea1c2a 100644
--- a/core/config/schema/core.data_types.schema.yml
+++ b/core/config/schema/core.data_types.schema.yml
@@ -79,6 +79,12 @@ uuid:
   constraints:
     Uuid: {}
 
+machine_name:
+  type: string
+  label: 'Machine name'
+  constraints:
+    MachineName: {}
+
 # PHP Date format string that is translatable.
 date_format:
   type: string
@@ -129,7 +135,7 @@ filter:
   label: 'Filter'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     provider:
       type: string
@@ -289,7 +295,7 @@ block_settings:
   label: 'Block settings'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
@@ -320,7 +326,7 @@ condition.plugin:
   label: 'Condition'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     negate:
       type: boolean
@@ -338,7 +344,7 @@ display_variant.plugin:
   label: 'Display variant'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
@@ -367,7 +373,7 @@ field_config_base:
   type: config_entity
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     field_name:
       type: string
@@ -414,7 +420,7 @@ core.date_format.*:
   label: 'Date format'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
diff --git a/core/config/schema/core.entity.schema.yml b/core/config/schema/core.entity.schema.yml
index df2a2fd..ba1323d 100644
--- a/core/config/schema/core.entity.schema.yml
+++ b/core/config/schema/core.entity.schema.yml
@@ -5,7 +5,7 @@ core.entity_view_mode.*.*:
   label: 'Entity view mode settings'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
@@ -22,7 +22,7 @@ core.entity_form_mode.*.*:
   label: 'Entity form mode settings'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
@@ -40,7 +40,7 @@ core.entity_view_display.*.*.*:
   label: 'Entity display'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     targetEntityType:
       type: string
@@ -91,7 +91,7 @@ core.entity_form_display.*.*.*:
   label: 'Entity form display'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     targetEntityType:
       type: string
diff --git a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/MachineNameConstraint.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/MachineNameConstraint.php
new file mode 100644
index 0000000..0607656
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/MachineNameConstraint.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * Validates a machine name.
+ *
+ * @Constraint(
+ *   id = "MachineName",
+ *   label = @Translation("Machine name", context = "Validation"),
+ * )
+ */
+class MachineNameConstraint extends Constraint {
+
+  public $message = 'This value should be a valid machine name.';
+
+}
diff --git a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/MachineNameConstraintValidator.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/MachineNameConstraintValidator.php
new file mode 100644
index 0000000..d25f1da
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/MachineNameConstraintValidator.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+
+/**
+ * Machine name constraint validator.
+ */
+class MachineNameConstraintValidator extends ConstraintValidator {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validate($value, Constraint $constraint) {
+    if (!preg_match('/^[a-z0-9_]+$/', $value)) {
+      $this->context->addViolation($constraint->message);
+    }
+  }
+
+}
diff --git a/core/modules/block/config/schema/block.schema.yml b/core/modules/block/config/schema/block.schema.yml
index 16d79bc..648c8b7 100644
--- a/core/modules/block/config/schema/block.schema.yml
+++ b/core/modules/block/config/schema/block.schema.yml
@@ -5,7 +5,7 @@ block.block.*:
   label: 'Block'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     theme:
       type: string
diff --git a/core/modules/block_content/config/schema/block_content.schema.yml b/core/modules/block_content/config/schema/block_content.schema.yml
index 2e7c338..2c4f09d 100644
--- a/core/modules/block_content/config/schema/block_content.schema.yml
+++ b/core/modules/block_content/config/schema/block_content.schema.yml
@@ -5,7 +5,7 @@ block_content.type.*:
   label: 'Custom block type settings'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
diff --git a/core/modules/comment/config/schema/comment.schema.yml b/core/modules/comment/config/schema/comment.schema.yml
index 045e9ad..67220ce 100644
--- a/core/modules/comment/config/schema/comment.schema.yml
+++ b/core/modules/comment/config/schema/comment.schema.yml
@@ -47,7 +47,7 @@ comment.type.*:
   label: 'Comment type settings'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
diff --git a/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml b/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml
index ce894c2..daf46ba 100644
--- a/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml
+++ b/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml
@@ -283,7 +283,7 @@ wrapping.test.other_double_brackets.*:
   type: test.double_brackets.[id]
   mapping:
     id:
-      type: string
+      type: machine_name
     foo:
       type: string
     bar:
diff --git a/core/modules/config/tests/config_test/config/install/config_test.validation.yml b/core/modules/config/tests/config_test/config/install/config_test.validation.yml
index fa84ff3..2832560 100644
--- a/core/modules/config/tests/config_test/config/install/config_test.validation.yml
+++ b/core/modules/config/tests/config_test/config/install/config_test.validation.yml
@@ -6,3 +6,4 @@ giraffe:
   hum1: hum1
   hum2: hum2
 uuid: '7C30C50E-641A-4E34-A7F1-46BCFB9BE5A3'
+machine_name: 'foo'
diff --git a/core/modules/config/tests/config_test/config/schema/config_test.schema.yml b/core/modules/config/tests/config_test/config/schema/config_test.schema.yml
index c25a577..896d6b5 100644
--- a/core/modules/config/tests/config_test/config/schema/config_test.schema.yml
+++ b/core/modules/config/tests/config_test/config/schema/config_test.schema.yml
@@ -4,7 +4,7 @@ config_test_dynamic:
   type: config_entity
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
@@ -43,7 +43,7 @@ config_test.query.*:
   type: config_entity
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
@@ -104,7 +104,7 @@ config_test.no_status.default:
   label: 'Configuration no status default'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
@@ -195,3 +195,5 @@ config_test.validation:
             callback: [\Drupal\config_test\ConfigValidation, validateGiraffes]
     uuid:
       type: uuid
+    machine_name:
+      type: machine_name
diff --git a/core/modules/config/tests/config_test/src/ConfigValidation.php b/core/modules/config/tests/config_test/src/ConfigValidation.php
index 9c69394..5934ed1 100644
--- a/core/modules/config/tests/config_test/src/ConfigValidation.php
+++ b/core/modules/config/tests/config_test/src/ConfigValidation.php
@@ -74,7 +74,7 @@ public static function validateGiraffes($string, ExecutionContextInterface $cont
    *   The validation execution context.
    */
   public static function validateMapping($mapping, ExecutionContextInterface $context) {
-    if ($diff = array_diff(array_keys($mapping), ['llama', 'cat', 'giraffe', 'uuid', '_core'])) {
+    if ($diff = array_diff(array_keys($mapping), ['llama', 'cat', 'giraffe', 'uuid', 'machine_name', '_core'])) {
       $context->addViolation('Missing giraffe.');
     }
   }
diff --git a/core/modules/config_translation/tests/modules/config_translation_test/config/schema/config_translation_test.schema.yml b/core/modules/config_translation/tests/modules/config_translation_test/config/schema/config_translation_test.schema.yml
index 63b8475..9dbbffb 100644
--- a/core/modules/config_translation/tests/modules/config_translation_test/config/schema/config_translation_test.schema.yml
+++ b/core/modules/config_translation/tests/modules/config_translation_test/config/schema/config_translation_test.schema.yml
@@ -5,7 +5,7 @@ config_translation_test.content:
   label: 'Content'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'Category identifier'
     label:
       type: label
diff --git a/core/modules/contact/config/schema/contact.schema.yml b/core/modules/contact/config/schema/contact.schema.yml
index 1f0585d..d56cb45 100644
--- a/core/modules/contact/config/schema/contact.schema.yml
+++ b/core/modules/contact/config/schema/contact.schema.yml
@@ -5,7 +5,7 @@ contact.form.*:
   label: 'Contact form'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
diff --git a/core/modules/field/config/schema/field.schema.yml b/core/modules/field/config/schema/field.schema.yml
index ca182c4..6b3d025 100644
--- a/core/modules/field/config/schema/field.schema.yml
+++ b/core/modules/field/config/schema/field.schema.yml
@@ -13,7 +13,7 @@ field.storage.*.*:
   label: 'Field'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     field_name:
       type: string
diff --git a/core/modules/field_layout/config/schema/field_layout.schema.yml b/core/modules/field_layout/config/schema/field_layout.schema.yml
index 185fb4e..9c7ab0f 100644
--- a/core/modules/field_layout/config/schema/field_layout.schema.yml
+++ b/core/modules/field_layout/config/schema/field_layout.schema.yml
@@ -9,7 +9,7 @@ field_layout.third_party_settings:
   label: 'Per-view-mode field layout settings'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'Layout ID'
     settings:
       type: layout_plugin.settings.[%parent.id]
diff --git a/core/modules/image/config/schema/image.schema.yml b/core/modules/image/config/schema/image.schema.yml
index 924d454..7346626 100644
--- a/core/modules/image/config/schema/image.schema.yml
+++ b/core/modules/image/config/schema/image.schema.yml
@@ -15,7 +15,7 @@ image.style.*:
         type: mapping
         mapping:
           id:
-            type: string
+            type: machine_name
           data:
             type: image.effect.[%parent.id]
           weight:
diff --git a/core/modules/language/config/schema/language.schema.yml b/core/modules/language/config/schema/language.schema.yml
index 91ce2d1..52d37c3 100644
--- a/core/modules/language/config/schema/language.schema.yml
+++ b/core/modules/language/config/schema/language.schema.yml
@@ -89,7 +89,7 @@ language.entity.*:
   label: 'Language'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
@@ -109,7 +109,7 @@ language.content_settings.*.*:
   label: 'Content Language Settings'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     target_entity_type_id:
       type: string
diff --git a/core/modules/media/config/schema/media.schema.yml b/core/modules/media/config/schema/media.schema.yml
index dad5189..8fe5ea0 100644
--- a/core/modules/media/config/schema/media.schema.yml
+++ b/core/modules/media/config/schema/media.schema.yml
@@ -11,7 +11,7 @@ media.type.*:
   label: 'Media type'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'Machine name'
     label:
       type: label
diff --git a/core/modules/rdf/config/schema/rdf.schema.yml b/core/modules/rdf/config/schema/rdf.schema.yml
index a331382..3c8b568 100644
--- a/core/modules/rdf/config/schema/rdf.schema.yml
+++ b/core/modules/rdf/config/schema/rdf.schema.yml
@@ -5,7 +5,7 @@ rdf.mapping.*.*:
   label: 'RDF mapping'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     targetEntityType:
       type: string
diff --git a/core/modules/responsive_image/config/schema/responsive_image.schema.yml b/core/modules/responsive_image/config/schema/responsive_image.schema.yml
index f05a8e2..7576d1a 100644
--- a/core/modules/responsive_image/config/schema/responsive_image.schema.yml
+++ b/core/modules/responsive_image/config/schema/responsive_image.schema.yml
@@ -5,7 +5,7 @@ responsive_image.styles.*:
   label: 'Responsive image style'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'Machine-readable name'
     label:
       type: label
diff --git a/core/modules/rest/config/schema/rest.schema.yml b/core/modules/rest/config/schema/rest.schema.yml
index 98b35ae..d4e447c 100644
--- a/core/modules/rest/config/schema/rest.schema.yml
+++ b/core/modules/rest/config/schema/rest.schema.yml
@@ -88,7 +88,7 @@ rest.resource.*:
   label: 'REST resource config'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'REST resource config ID'
     plugin_id:
       type: string
diff --git a/core/modules/search/config/schema/search.schema.yml b/core/modules/search/config/schema/search.schema.yml
index 2ed4c09..ff232c6 100644
--- a/core/modules/search/config/schema/search.schema.yml
+++ b/core/modules/search/config/schema/search.schema.yml
@@ -72,7 +72,7 @@ search.page.*:
   label: 'Search page'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
diff --git a/core/modules/shortcut/config/schema/shortcut.schema.yml b/core/modules/shortcut/config/schema/shortcut.schema.yml
index 7d9420b..c131282 100644
--- a/core/modules/shortcut/config/schema/shortcut.schema.yml
+++ b/core/modules/shortcut/config/schema/shortcut.schema.yml
@@ -5,7 +5,7 @@ shortcut.set.*:
   label: 'Shortcut settings'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml
index a6f61b6..607cefc 100644
--- a/core/modules/system/config/schema/system.schema.yml
+++ b/core/modules/system/config/schema/system.schema.yml
@@ -230,7 +230,7 @@ system.menu.*:
   label: 'Menu'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
@@ -247,7 +247,7 @@ system.action.*:
   label: 'System action'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
diff --git a/core/modules/system/tests/modules/entity_test/config/schema/entity_test.schema.yml b/core/modules/system/tests/modules/entity_test/config/schema/entity_test.schema.yml
index d34d949..ab91b51 100644
--- a/core/modules/system/tests/modules/entity_test/config/schema/entity_test.schema.yml
+++ b/core/modules/system/tests/modules/entity_test/config/schema/entity_test.schema.yml
@@ -22,7 +22,7 @@ entity_test.entity_test_bundle.*:
       type: label
       label: 'Label'
     id:
-      type: string
+      type: machine_name
       label: 'Machine-readable name'
     description:
       type: text
diff --git a/core/modules/system/tests/modules/module_installer_config_test/config/schema/module_installer_config_test.schema.yml b/core/modules/system/tests/modules/module_installer_config_test/config/schema/module_installer_config_test.schema.yml
index cb39936..2ff2bdb 100644
--- a/core/modules/system/tests/modules/module_installer_config_test/config/schema/module_installer_config_test.schema.yml
+++ b/core/modules/system/tests/modules/module_installer_config_test/config/schema/module_installer_config_test.schema.yml
@@ -3,7 +3,7 @@ module_installer_config_test.type.*:
   label: 'Test entity type'
   mapping:
     id:
-      type: string
+      type: machine_name
     name:
       type: label
       label: 'Name'
diff --git a/core/modules/tour/config/schema/tour.schema.yml b/core/modules/tour/config/schema/tour.schema.yml
index caf7363..6920555 100644
--- a/core/modules/tour/config/schema/tour.schema.yml
+++ b/core/modules/tour/config/schema/tour.schema.yml
@@ -5,7 +5,7 @@ tour.tour.*:
   label: 'Tour settings'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
@@ -31,7 +31,7 @@ tour.tip:
   label: 'Tour tip'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     plugin:
       type: string
diff --git a/core/modules/user/config/schema/user.schema.yml b/core/modules/user/config/schema/user.schema.yml
index 2f9bda4..cad8eb5 100644
--- a/core/modules/user/config/schema/user.schema.yml
+++ b/core/modules/user/config/schema/user.schema.yml
@@ -108,7 +108,7 @@ user.role.*:
   label: 'User role settings'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
diff --git a/core/modules/views/config/schema/views.data_types.schema.yml b/core/modules/views/config/schema/views.data_types.schema.yml
index 7736a74..fa69c5c 100644
--- a/core/modules/views/config/schema/views.data_types.schema.yml
+++ b/core/modules/views/config/schema/views.data_types.schema.yml
@@ -300,7 +300,7 @@ views_handler:
   type: mapping
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'A unique ID per handler type'
     table:
       type: string
diff --git a/core/modules/views/config/schema/views.schema.yml b/core/modules/views/config/schema/views.schema.yml
index 6a6c321..0176a15 100644
--- a/core/modules/views/config/schema/views.schema.yml
+++ b/core/modules/views/config/schema/views.schema.yml
@@ -70,7 +70,7 @@ views.view.*:
   label: 'View'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
@@ -101,7 +101,7 @@ views.view.*:
         label: 'Display settings'
         mapping:
           id:
-            type: string
+            type: machine_name
             label: 'Machine name'
           display_title:
             type: text
diff --git a/core/modules/workflows/config/schema/workflows.schema.yml b/core/modules/workflows/config/schema/workflows.schema.yml
index 42a5d97..770fed8 100644
--- a/core/modules/workflows/config/schema/workflows.schema.yml
+++ b/core/modules/workflows/config/schema/workflows.schema.yml
@@ -3,7 +3,7 @@ workflows.workflow.*:
   label: 'Workflow'
   mapping:
     id:
-      type: string
+      type: machine_name
       label: 'ID'
     label:
       type: label
diff --git a/core/tests/Drupal/KernelTests/Core/Validation/ConstraintsTest.php b/core/tests/Drupal/KernelTests/Core/Validation/ConstraintsTest.php
index 8e17422..e9badd9 100644
--- a/core/tests/Drupal/KernelTests/Core/Validation/ConstraintsTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Validation/ConstraintsTest.php
@@ -26,20 +26,43 @@ protected function setUp() {
   }
 
   /**
-   * @see \Drupal\Core\Validation\Plugin\Validation\Constraint\UuidConstraint
+   * Test validation of various constraints.
+   *
+   * @dataProvider validationsDataProvider
    */
-  public function testUuid() {
+  public function testValidation($test_key, $value, $violatioin_count) {
     $typed_config_manager = \Drupal::service('config.typed');
-    /** @var \Drupal\Core\Config\Schema\TypedConfigInterface $typed_config */
     $typed_config = $typed_config_manager->get('config_test.validation');
-    $typed_config->get('uuid')
-      ->setValue(\Drupal::service('uuid')->generate());
-
-    $this->assertCount(0, $typed_config->validate());
+    $typed_config->get($test_key)->setValue($value);
+    $this->assertCount($violatioin_count, $typed_config->validate());
+  }
 
-    $typed_config->get('uuid')
-      ->setValue(\Drupal::service('uuid')->generate() . '-invalid');
-    $this->assertCount(1, $typed_config->validate());
+  /**
+   * Data provider for ::testValidation.
+   */
+  public function validationsDataProvider() {
+    return [
+      'Valid UUID' => [
+        'uuid',
+        'd320a25d-7a65-4d27-ad02-2e5455493127',
+        0,
+      ],
+      'Invalid UUID' => [
+        'uuid',
+        'd320a25d-7a65-4d27-ad02-2e5455493127-invalid',
+        1,
+      ],
+      'Valid machine name' => [
+        'machine_name',
+        'foo_machine_name',
+        0,
+      ],
+      'Invalid machine name' => [
+        'machine_name',
+        'invalid machine name',
+        1,
+      ],
+    ];
   }
 
 }
