diff --git a/entity.module b/entity.module
index 45d2231..765a1b8 100644
--- a/entity.module
+++ b/entity.module
@@ -1208,3 +1208,12 @@ function _entity_info_add_metadata_callbacks(&$entity_info) {
     $entity_info['taxonomy_vocabulary']['token type'] = 'vocabulary';
   }
 }
+
+/**
+ * Implements hook_ctools_plugin_directory().
+ */
+function entity_ctools_plugin_directory($module, $plugin) {
+  if ($module == 'ctools' && !empty($plugin)) {
+    return "plugins/$plugin";
+  }
+}
diff --git a/plugins/access/entity.inc b/plugins/access/entity.inc
new file mode 100644
index 0000000..d4810e5
--- /dev/null
+++ b/plugins/access/entity.inc
@@ -0,0 +1,92 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Plugin to provide access control based upon entity-metadata.
+ */
+
+/**
+ * Plugins declaration.
+ */
+$plugin = array(
+  'title' => t("Entity property"),
+  'description' => t('Control access by entity property.'),
+  'callback' => 'entity_entity_metadata_ctools_access_check',
+  'settings form' => 'entity_entity_metadata_ctools_access_settings',
+  'summary' => 'entity_entity_metadata_ctools_access_summary',
+  'get child' => 'entity_entity_metadata_ctools_access_get_child',
+  'get children' => 'entity_entity_metadata_ctools_access_get_children',
+);
+
+function entity_entity_metadata_ctools_access_get_child($plugin, $parent, $child) {
+  $plugins = entity_entity_metadata_ctools_access_get_children($plugin, $parent);
+  return $plugins[$parent . ':' . $child];
+}
+
+function entity_entity_metadata_ctools_access_get_children($plugin, $parent) {
+  $info = entity_get_property_info();
+
+  // Site isn't a real entity, so remove it.
+  unset($info['site']);
+
+  $plugins = array();
+  foreach ($info as $entity_type => $data) {
+    foreach ($data['properties'] as $name => $property) {
+      if (!empty($property['access callback']) || !empty($property['setter permission'])) {
+        $property += array('description' => '');
+
+        $plugin['title'] = t('@entity: @label', array('@entity' => ucfirst($entity_type), '@label' => $property['label']));
+        $plugin['keyword'] = $entity_type . ':' . $name;
+        $plugin['description'] = t('Control access of @label property.', array('@label' => $property['label']));
+        $plugin['name'] = $parent. ':' . $entity_type . '_' . $name;
+        $plugin['required context'] = new ctools_context_required(t(ucfirst($entity_type)), $entity_type);
+        $plugins[$parent. ':' . $entity_type . '_' . $name] = $plugin;
+      }
+    }
+  }
+
+  return $plugins;
+}
+
+/**
+ * Form callback.
+ */
+function entity_entity_metadata_ctools_access_settings($form, &$form_state, $conf) {
+  // This is needed to allow other settings to pass.
+  return $form;
+}
+
+/**
+ * Check for access.
+ */
+function entity_entity_metadata_ctools_access_check($conf, $context, $plugin) {
+  if (empty($context) || empty($context->data)) {
+    return;
+  }
+
+  // Get the entity.
+  $entity = $context->data;
+  list($entity_type, $name) = explode(':', $plugin['keyword'], 2);
+
+  $wrapper = entity_metadata_wrapper($entity_type, $entity);
+  if (!$wrapper) {
+    return;
+  }
+
+  // Access check on the property.
+  if (!$wrapper->{$name}->access('view')) {
+    return;
+  }
+
+  return TRUE;
+}
+
+
+/**
+ * Provide a summary description based upon the checked entity_bundle.
+ */
+function entity_entity_metadata_ctools_access_summary($conf, $context, $plugin) {
+  return t('"@s" @name', array('@s' => $context->identifier, '@name' => $plugin['title']));
+}
+
