diff --git a/includes/rules.core.inc b/includes/rules.core.inc
index 4c6a356..9fd0272 100644
--- a/includes/rules.core.inc
+++ b/includes/rules.core.inc
@@ -38,6 +38,14 @@ class RulesEntityController extends EntityAPIControllerExportable {
       $modules[$row->id][] = $row->module;
     }
 
+    $result = db_select('rules_roles')
+      ->fields('rules_roles', array('id', 'rid'))
+      ->condition('id', $ids, 'IN')
+      ->execute();
+    foreach ($result as $row) {
+      $roles[$row->id][$row->rid] = $row->rid;
+    }
+
     $entities = array();
     foreach ($queried_entities as $record) {
       $entity = $record->data;
@@ -49,6 +57,7 @@ class RulesEntityController extends EntityAPIControllerExportable {
       // Add any tags or dependencies.
       $entity->dependencies = isset($modules[$entity->id]) ? $modules[$entity->id] : array();
       $entity->tags = isset($tags[$entity->id]) ? $tags[$entity->id] : array();
+      $entity->roles = isset($roles[$entity->id]) ? $roles[$entity->id] : array();
       $entities[$entity->id] = $entity;
     }
     $queried_entities = $entities;
@@ -111,7 +120,7 @@ class RulesEntityController extends EntityAPIControllerExportable {
     // Create an empty configuration, re-set basic keys and import.
     $config = rules_plugin_factory($export['PLUGIN']);
     $config->name = $name;
-    foreach (array('label', 'active', 'weight', 'tags') as $key) {
+    foreach (array('label', 'active', 'weight', 'tags', 'roles') as $key) {
       if (isset($export[strtoupper($key)])) {
         $config->$key = $export[strtoupper($key)];
       }
@@ -134,6 +143,7 @@ class RulesEntityController extends EntityAPIControllerExportable {
 
     $return = parent::save($rules_config, $transaction);
     $this->storeTags($rules_config);
+    $this->storeRoles($rules_config);
     if ($rules_config instanceof RulesTriggerableInterface) {
       $this->storeEvents($rules_config);
     }
@@ -158,6 +168,22 @@ class RulesEntityController extends EntityAPIControllerExportable {
   }
 
   /**
+   * Save role information to the rules_roles table.
+   */
+  protected function storeRoles($rules_config) {
+    db_delete('rules_roles')
+      ->condition('id', $rules_config->id)
+      ->execute();
+    if (!empty($rules_config->roles)) {
+      foreach ($rules_config->roles as $rid) {
+        db_insert('rules_roles')
+          ->fields(array('id', 'rid'), array($rules_config->id, $rid))
+          ->execute();
+      }
+    }
+  }
+
+  /**
    * Save event information to the rules_trigger table.
    */
   protected function storeEvents(RulesTriggerableInterface $rules_config) {
@@ -228,6 +254,9 @@ class RulesEntityController extends EntityAPIControllerExportable {
         db_delete('rules_tags')
           ->condition('id', $config->id)
           ->execute();
+        db_delete('rules_roles')
+          ->condition('id', $config->id)
+          ->execute();
         db_delete('rules_dependencies')
           ->condition('id', $config->id)
           ->execute();
@@ -1240,6 +1269,9 @@ abstract class RulesPlugin extends RulesExtendable {
     if (!empty($this->tags)) {
       $export_cfg[$this->name]['TAGS'] = $this->tags;
     }
+    if (!empty($this->roles)) {
+      $export_cfg[$this->name]['ROLES'] = $this->roles;
+    }
     if ($modules = $this->dependencies()) {
       $export_cfg[$this->name]['REQUIRES'] = $modules;
     }
diff --git a/modules/rules_core.rules.inc b/modules/rules_core.rules.inc
index 6f00996..c450fe9 100644
--- a/modules/rules_core.rules.inc
+++ b/modules/rules_core.rules.inc
@@ -299,11 +299,12 @@ function rules_element_invoke_component_features_export(&$export, &$pipe, $modul
  * Access callback for the invoke component condition/action.
  */
 function rules_element_invoke_component_access_callback($type, $name) {
-  // Only allow access to the action/condition if the user has access to the
-  // component.
+  global $user;
   // Cut of the leading 'component_' from the action name.
   $component = rules_config_load(substr($name, 10));
-  return $component && $component->access();
+  // Limit access by role, if any roles were selected for the component.
+  $component_access = empty($component->roles) ? TRUE : array_intersect(array_keys($component->roles), array_keys($user->roles));
+  return user_access('bypass rules access', $user) || $component_access;
 }
 
 /**
diff --git a/rules.install b/rules.install
index 370226e..2c730b1 100644
--- a/rules.install
+++ b/rules.install
@@ -167,6 +167,27 @@ function rules_schema() {
       'id' => array('rules_config' => 'id'),
     ),
   );
+  $schema['rules_roles'] = array(
+    'fields' => array(
+      'id' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'description' => 'The primary identifier of the configuration.',
+      ),
+      'rid' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'description' => 'Unique role id.',
+      ),
+    ),
+    'primary key' => array('id', 'rid'),
+    'foreign keys' => array(
+      'id' => array('rules_config' => 'id'),
+      'rid' => array('role' => 'rid'),
+    ),
+  );
   $schema['cache_rules'] = drupal_get_schema_unprocessed('system', 'cache');
   $schema['cache_rules']['description'] = 'Cache table for the rules engine to store configured items.';
   return $schema;
@@ -406,3 +427,31 @@ function rules_update_7206() {
 function rules_update_7207() {
   // The update system is going to flush all caches anyway, so nothing to do.
 }
+
+/**
+ * Create roles table to store component-role to manage access.
+ */
+function rules_update_7208() {
+  $schema['rules_roles'] = array(
+    'fields' => array(
+      'id' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'description' => 'The primary identifier of the configuration.',
+      ),
+      'rid' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'description' => 'Unique role id.',
+      ),
+    ),
+    'primary key' => array('id', 'rid'),
+    'foreign keys' => array(
+      'id' => array('rules_config' => 'id'),
+      'rid' => array('role' => 'rid'),
+    ),
+  );
+  db_create_table('rules_roles', $schema['rules_roles']);
+}
diff --git a/tests/rules.test b/tests/rules.test
index da0c8f5..711a414 100644
--- a/tests/rules.test
+++ b/tests/rules.test
@@ -140,6 +140,42 @@ class RulesTestCase extends DrupalWebTestCase {
   }
 
   /**
+   * Test role access.
+   */
+  function testRoleAccess() {
+    // Create a normal user.
+    $normal_user = $this->drupalCreateUser();
+    // Create a role for granting access to the rule component.
+    $this->normal_role = $this->drupalCreateRole(array());
+    // Create an 'action set' rule component with permission access to that
+    // role.
+    $action_set = rules_action_set(array('node' => array('type' => 'node')));
+    $action_set->roles = array($this->normal_role);
+    $action_set->save('rules_test_roles');
+
+    // Login as normal user, force the user object to be the current one as
+    // there's a global $user call in the permission check.
+    $this->drupalLogin($normal_user);
+    global $user;
+    $user = user_load($normal_user->uid);
+
+    $this->assertFalse(rules_action('component_rules_test_roles')->access(), 'Authenticated user without the correct role can\'t access to the rule component.');
+
+    // Assign the role that will have permissions for the rule component.
+    $normal_user->roles[$this->normal_role] = $this->normal_role;
+    $user = user_save($normal_user);
+
+    $this->assertTrue(rules_action('component_rules_test_roles')->access(), 'Authenticated user with the correct role can access to the rule component.');
+
+    // Logout and access as anonymous.
+    $this->drupalLogout();
+    global $user;
+    $user = user_load(0);
+
+    $this->assertFalse(rules_action('component_rules_test_roles')->access(), 'Anonymous user can\'t access to the rule component.');
+  }
+
+  /**
    * Test setting up an action with some action_info and serializing and
    * executing it.
    */
@@ -266,6 +302,35 @@ class RulesTestCase extends DrupalWebTestCase {
       ->condition('id', $rule->id)
       ->execute();
     $this->assertEqual($result->fetchField(), FALSE, 'Deleted associated tags.');
+
+    // Tests CRUD for roles - making sure the tags are stored properly..
+    // Create an 'action set' rule component with permission access to
+    // authenticated users.
+    $action_set = rules_action_set(array('node' => array('type' => 'node')));
+    $action_set->roles = array(DRUPAL_AUTHENTICATED_RID);
+    $action_set->save('rules_test_roles');
+    $result = db_select('rules_roles')
+      ->fields('rules_roles', array('rid'))
+      ->condition('id', $action_set->id)
+      ->execute();
+    $this->assertEqual($result->fetchField(), DRUPAL_AUTHENTICATED_RID, 'Associated role has been saved.');
+    // Try updating.
+    $action_set->roles = array(DRUPAL_AUTHENTICATED_RID, DRUPAL_ANONYMOUS_RID);
+    $action_set->integrityCheck()->save();
+    $result = db_select('rules_roles')
+      ->fields('rules_roles', array('rid'))
+      ->condition('id', $action_set->id)
+      ->execute()
+      ->fetchCol();
+    $this->assertTrue(in_array($action_set->roles[0], $result) && in_array($action_set->roles[1], $result), 'Updated associated roles.');
+    // Try deleting.
+    $action_set->delete();
+    $result = db_select('rules_roles')
+      ->fields('rules_roles', array('rid'))
+      ->condition('id', $action_set->id)
+      ->execute();
+    $this->assertEqual($result->fetchField(), FALSE, 'Deleted associated roles.');
+
   }
 
   /**
diff --git a/ui/ui.core.inc b/ui/ui.core.inc
index bc69ac4..9c5edad 100644
--- a/ui/ui.core.inc
+++ b/ui/ui.core.inc
@@ -478,6 +478,22 @@ class RulesPluginUI extends FacesExtender implements RulesPluginUIInterface {
         '#limit_validation_errors' => array(array('vars')),
         '#submit' => array('rules_form_submit_rebuild'),
       );
+      // Display roles to manage access.
+      $role_options = array_map('check_plain', user_roles());
+      $form['settings']['roles'] = array(
+        '#type' => 'fieldset',
+        '#collapsible' => TRUE,
+        '#collapsed' => TRUE,
+        '#prefix' => '<div id="rules-component-roles">',
+        '#suffix' => '</div>',
+        '#title' => t('Roles'),
+        '#description' => t('Select the roles that will have access to execute this component. Selecting none will grant access to all roles.'),
+      );
+      $form['settings']['roles']['items'] = array(
+        '#type' => 'checkboxes',
+        '#options' => $role_options,
+        '#default_value' => isset($this->element->roles) ? $this->element->roles : array(),
+      );
     }
 
     // TODO: Attach field form thus description.
@@ -522,6 +538,15 @@ class RulesPluginUI extends FacesExtender implements RulesPluginUIInterface {
       }
       unset($input['vars']);
     }
+
+    $this->element->roles = array();
+    if (isset($form_values['roles']['items'])) {
+      foreach ($form_values['roles']['items'] as $item) {
+        if ($item) {
+          $this->element->roles[$item] = $item;
+        }
+      }
+    }
   }
 
   public function settingsFormValidate($form, &$form_state) {
