diff --git a/core/modules/system/src/EventSubscriber/GroupRouteSubscriber.php b/core/modules/system/src/EventSubscriber/GroupRouteSubscriber.php
new file mode 100644
index 0000000..5ec970e
--- /dev/null
+++ b/core/modules/system/src/EventSubscriber/GroupRouteSubscriber.php
@@ -0,0 +1,145 @@
+<?php
+
+namespace Drupal\system\EventSubscriber;
+
+use Drupal\Core\Routing\RouteSubscriberBase;
+use Symfony\Component\Routing\RouteCollection;
+use Drupal\Core\Access\AccessManagerInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Menu\MenuLinkTreeInterface;
+use Drupal\Core\Menu\MenuTreeParameters;
+use Drupal\user\Entity\User;
+
+/**
+ * Alters routes, which are parents for other routes.
+ */
+class GroupRouteSubscriber extends RouteSubscriberBase {
+
+  /**
+   * The access manager.
+   *
+   * @var \Drupal\Core\Access\AccessManagerInterface
+   */
+  protected $accessManager;
+
+  /**
+   * The menu link tree service.
+   *
+   * @var \Drupal\Core\Menu\MenuLinkTreeInterface
+   */
+  protected $menuLinkTree;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs a new GroupRouteSubscriber.
+   *
+   * @param \Drupal\Core\Access\AccessManagerInterface $access_manager
+   *   The access manager.
+   * @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_link_tree
+   *   The menu link tree service.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct(AccessManagerInterface $access_manager, MenuLinkTreeInterface $menu_link_tree, EntityTypeManagerInterface $entity_type_manager) {
+    $this->accessManager = $access_manager;
+    $this->menuLinkTree = $menu_link_tree;
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function alterRoutes(RouteCollection $collection) {
+    // Load all roles and leave only non-admin ones with necessary permission.
+    try {
+      $roles = $this->entityTypeManager->getStorage('user_role')->loadMultiple();
+      $user_storage = $this->entityTypeManager->getStorage('user');
+    }
+    catch (\Exception $e) {
+      return;
+    }
+    $access_roles = [];
+    $admin_role = '';
+    foreach ($roles as $role_id => $role) {
+      if ($role->isAdmin()) {
+        $admin_role = $role_id;
+        continue;
+      }
+      if ($role->hasPermission('access administration pages')) {
+        $access_roles[$role_id] = $user_storage->create([
+          'roles' => [
+            $role_id,
+          ],
+        ]);
+      }
+    }
+    if (empty($admin_role) || empty($access_roles)) {
+      return;
+    }
+    foreach ($collection->all() as $route_id => $route) {
+      if ($route->hasOption('_group_route')) {
+        // Add admin role in order to restrict access for other roles.
+        $route_accessible_roles = [$admin_role];
+        // Perform check.
+        $this->checkAccess($route_accessible_roles, $collection, $route_id, NULL, NULL, $access_roles);
+        $route->setRequirement('_role', (string) implode('+', $route_accessible_roles));
+      }
+    }
+  }
+
+  /**
+   * Checks route and its children.
+   *
+   * @param array $route_accessible_roles
+   *   Array with role names, which are allowed to access route.
+   * @param Symfony\Component\Routing\RouteCollection $collection
+   *   Routes collection.
+   * @param string $route_id
+   *   Route ID.
+   * @param Drupal\user\Entity\User $test_user
+   *   User object for test.
+   * @param string $test_role
+   *   User's role to be added in array.
+   * @param array $access_roles
+   *   Array with test users for access checking.
+   */
+  protected function checkAccess(array &$route_accessible_roles, RouteCollection $collection, $route_id, User $test_user = NULL, $test_role = NULL, array $access_roles = NULL) {
+    // Load all menu links below route
+    // and check if route has any accessible children by any of roles.
+    $parameters = new MenuTreeParameters();
+    $parameters->setRoot($route_id)->excludeRoot()->setTopLevelOnly()->onlyEnabledLinks();
+    $tree = $this->menuLinkTree->load(NULL, $parameters);
+    if (empty($tree)) {
+      if ($collection->get($route_id)->hasOption('_group_route')) {
+        return;
+      }
+      $route_accessible_roles[] = $test_role;
+    }
+    else {
+      foreach ($tree as $element_id => $element) {
+        $url = $element->link->getUrlObject();
+        if (!empty($access_roles)) {
+          foreach ($access_roles as $route_role => $role_user) {
+            if ($this->accessManager->checkNamedRoute($url->getRouteName(), $url->getRouteParameters(), $role_user) && !in_array($route_role, $route_accessible_roles)) {
+              // User is allowed to visit this page, but need to check,
+              // if it's also group route with inaccessible children.
+              $this->checkAccess($route_accessible_roles, $collection, $element_id, $role_user, $route_role);
+            }
+          }
+        }
+        else {
+          if ($this->accessManager->checkNamedRoute($url->getRouteName(), $url->getRouteParameters(), $test_user) && !in_array($test_role, $route_accessible_roles)) {
+            $route_accessible_roles[] = $test_role;
+          }
+        }
+      }
+    }
+  }
+
+}
diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml
index ffca932..0d6198e 100644
--- a/core/modules/system/system.routing.yml
+++ b/core/modules/system/system.routing.yml
@@ -45,6 +45,8 @@ system.admin_structure:
     _title: 'Structure'
   requirements:
     _permission: 'access administration pages'
+  options:
+    _group_route: TRUE
 
 system.admin_reports:
   path: '/admin/reports'
@@ -53,6 +55,8 @@ system.admin_reports:
     _title: 'Reports'
   requirements:
     _permission: 'access site reports'
+  options:
+    _group_route: TRUE
 
 system.admin_config_media:
   path: '/admin/config/media'
@@ -61,6 +65,8 @@ system.admin_config_media:
     _title: 'Media'
   requirements:
     _permission: 'access administration pages'
+  options:
+    _group_route: TRUE
 
 system.admin_config_services:
   path: '/admin/config/services'
@@ -69,6 +75,8 @@ system.admin_config_services:
     _title: 'Web services'
   requirements:
     _permission: 'access administration pages'
+  options:
+    _group_route: TRUE
 
 system.admin_config_development:
   path: '/admin/config/development'
@@ -77,6 +85,8 @@ system.admin_config_development:
     _title: 'Development'
   requirements:
     _permission: 'access administration pages'
+  options:
+    _group_route: TRUE
 
 system.admin_config_regional:
   path: '/admin/config/regional'
@@ -85,6 +95,8 @@ system.admin_config_regional:
     _title: 'Regional and language'
   requirements:
     _permission: 'access administration pages'
+  options:
+    _group_route: TRUE
 
 system.admin_config_search:
   path: '/admin/config/search'
@@ -93,6 +105,8 @@ system.admin_config_search:
     _title: 'Search and metadata'
   requirements:
     _permission: 'access administration pages'
+  options:
+    _group_route: TRUE
 
 system.admin_config_system:
   path: '/admin/config/system'
@@ -101,6 +115,8 @@ system.admin_config_system:
     _title: 'System'
   requirements:
     _permission: 'access administration pages'
+  options:
+    _group_route: TRUE
 
 system.admin_config_ui:
   path: '/admin/config/user-interface'
@@ -109,6 +125,8 @@ system.admin_config_ui:
     _title: 'User interface'
   requirements:
     _permission: 'access administration pages'
+  options:
+    _group_route: TRUE
 
 system.admin_config_workflow:
   path: '/admin/config/workflow'
@@ -117,6 +135,8 @@ system.admin_config_workflow:
     _title: 'Workflow'
   requirements:
     _permission: 'access administration pages'
+  options:
+    _group_route: TRUE
 
 system.admin_config_content:
   path: '/admin/config/content'
@@ -125,6 +145,8 @@ system.admin_config_content:
     _title: 'Content authoring'
   requirements:
     _permission: 'access administration pages'
+  options:
+    _group_route: TRUE
 
 system.cron:
   path: '/cron/{key}'
@@ -464,6 +486,8 @@ system.admin_config:
     _title: 'Configuration'
   requirements:
     _permission: 'access administration pages'
+  options:
+    _group_route: TRUE
 
 system.batch_page.html:
   path: '/batch'
@@ -506,6 +530,8 @@ system.admin_content:
     _title: 'Content'
   requirements:
     _permission: 'access administration pages'
+  options:
+    _group_route: TRUE
 
 system.entity_autocomplete:
   path: '/entity_reference_autocomplete/{target_type}/{selection_handler}/{selection_settings_key}'
diff --git a/core/modules/system/system.services.yml b/core/modules/system/system.services.yml
index 9db3db1..3f34007 100644
--- a/core/modules/system/system.services.yml
+++ b/core/modules/system/system.services.yml
@@ -23,6 +23,11 @@ services:
     class: Drupal\system\EventSubscriber\AdminRouteSubscriber
     tags:
       - { name: event_subscriber }
+  system.group_route.route_subscriber:
+    class: Drupal\system\EventSubscriber\GroupRouteSubscriber
+    arguments: ['@access_manager', '@menu.link_tree', '@entity_type.manager']
+    tags:
+      - { name: event_subscriber }
   theme.negotiator.system.batch:
     class: Drupal\system\Theme\BatchNegotiator
     arguments: ['@batch.storage', '@request_stack']
