Skip to content

Commit

Permalink
sssctl: Management of indexes on cache DBs.
Browse files Browse the repository at this point in the history
A new command was added to sssctl in order to manage indexes on the
cache DBs.

sssctl cache-index create -a attr [-d domain]
sssctl cache-index delete -a attr [-d domain]
sssctl cache-index list [-a attr] [-d domain]

:feature: sssctl is now able to create, list and delete indexes on
          the local caches. Indexes are useful for the new D-Bus
          ListByAttr() function.

:relnote: The new D-Bus function ListByAttr() allows the caller to
          look for users that have an attribute with a certain value.
          For performance reasons, it is recommended that the
          attribute is indexed both on the remote server and on the
          local cache. The sssctl tool now provides the cache-index
          command to help you manage indexes on the local cache.
  • Loading branch information
aplopez committed Oct 3, 2022
1 parent 0198f64 commit 1421fa4
Show file tree
Hide file tree
Showing 10 changed files with 485 additions and 47 deletions.
9 changes: 9 additions & 0 deletions src/db/sysdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
#define CACHE_TIMESTAMPS_FILE "timestamps_%s.ldb"
#define LOCAL_SYSDB_FILE "sssd.ldb"

#define SYSDB_INDEXES "@INDEXLIST"
#define SYSDB_IDXATTR "@IDXATTR"

#define SYSDB_BASE "cn=sysdb"
#define SYSDB_DOM_BASE "cn=%s,cn=sysdb"
#define SYSDB_USERS_CONTAINER "cn=users"
Expand Down Expand Up @@ -373,6 +376,12 @@ enum sysdb_member_type {
SYSDB_MEMBER_IP_NETWORK,
};

enum sysdb_index_actions {
SYSDB_IDX_CREATE,
SYSDB_IDX_DELETE,
SYSDB_IDX_LIST
};

/* These attributes are stored in the timestamp cache */
extern const char *sysdb_ts_cache_attrs[];

Expand Down
35 changes: 22 additions & 13 deletions src/db/sysdb_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,23 +157,32 @@ int sysdb_get_db_file(TALLOC_CTX *mem_ctx,
char **_ldb_file,
char **_ts_file)
{
char *ldb_file;
char *ts_file;
char *ldb_file = NULL;
char *ts_file = NULL;

if (_ldb_file != NULL) {
ldb_file = talloc_asprintf(mem_ctx, "%s/"CACHE_SYSDB_FILE,
base_path, name);
if (!ldb_file) {
return ENOMEM;
}
}
if (_ts_file != NULL) {
ts_file = talloc_asprintf(mem_ctx, "%s/"CACHE_TIMESTAMPS_FILE,
base_path, name);
if (!ts_file) {
talloc_free(ldb_file);
return ENOMEM;
}
}

ldb_file = talloc_asprintf(mem_ctx, "%s/"CACHE_SYSDB_FILE,
base_path, name);
if (!ldb_file) {
return ENOMEM;
if (_ldb_file != NULL) {
*_ldb_file = ldb_file;
}
ts_file = talloc_asprintf(mem_ctx, "%s/"CACHE_TIMESTAMPS_FILE,
base_path, name);
if (!ts_file) {
talloc_free(ldb_file);
return ENOMEM;
if (_ts_file != NULL) {
*_ts_file = ts_file;
}

*_ldb_file = ldb_file;
*_ts_file = ts_file;
return EOK;
}

Expand Down
199 changes: 189 additions & 10 deletions src/db/sysdb_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdbool.h>

#include "util/util.h"
#include "db/sysdb_private.h"
#include "db/sysdb_services.h"
Expand All @@ -35,15 +37,17 @@
#define SSS_SYSDB_BOTH_CACHE (SSS_SYSDB_CACHE | SSS_SYSDB_TS_CACHE)

/*
* The wrapper around ldb_modify that uses LDB_CONTROL_PERMISSIVE_MODIFY_OID
* so that on adds entries that already exist are skipped and similarly
* entries that are missing are ignored on deletes
* The wrapper around ldb_modify that optionally uses
* LDB_CONTROL_PERMISSIVE_MODIFY_OID so that on adds entries that already
* exist are skipped and similarly entries that are missing are ignored
* on deletes.
*
* Please note this function returns LDB error codes, not sysdb error
* codes on purpose, see usage in callers!
*/
int sss_ldb_modify_permissive(struct ldb_context *ldb,
struct ldb_message *msg)
int sss_ldb_modify(struct ldb_context *ldb,
struct ldb_message *msg,
bool permissive)
{
struct ldb_request *req;
int ret;
Expand All @@ -59,11 +63,13 @@ int sss_ldb_modify_permissive(struct ldb_context *ldb,

if (ret != LDB_SUCCESS) return ret;

ret = ldb_request_add_control(req, LDB_CONTROL_PERMISSIVE_MODIFY_OID,
false, NULL);
if (ret != LDB_SUCCESS) {
talloc_free(req);
return ret;
if (permissive) {
ret = ldb_request_add_control(req, LDB_CONTROL_PERMISSIVE_MODIFY_OID,
false, NULL);
if (ret != LDB_SUCCESS) {
talloc_free(req);
return ret;
}
}

ret = ldb_transaction_start(ldb);
Expand Down Expand Up @@ -114,6 +120,12 @@ int sss_ldb_modify_permissive(struct ldb_context *ldb,
return ret;
}

int sss_ldb_modify_permissive(struct ldb_context *ldb,
struct ldb_message *msg)
{
return sss_ldb_modify(ldb, msg, true);
}

#define ERROR_OUT(v, r, l) do { v = r; goto l; } while(0)


Expand Down Expand Up @@ -5625,3 +5637,170 @@ int sysdb_invalidate_cache_entry(struct sss_domain_info *domain,
talloc_zfree(tmp_ctx);
return ret;
}

/* === Operation On Indexes ================================== */
errno_t sysdb_ldb_list_indexes(TALLOC_CTX *mem_ctx,
struct ldb_context *ldb,
const char *attribute,
const char ***_indexes)
{
errno_t ret;
int j;
int i;
int ldb_ret;
unsigned int length;
unsigned int attr_length = (attribute == NULL ? 0 : strlen(attribute));
char *data;
struct ldb_dn *dn;
struct ldb_result *res;
struct ldb_message_element *el;
const char *attrs[] = { SYSDB_IDXATTR, NULL };
const char **indexes = NULL;

dn = ldb_dn_new(mem_ctx, ldb, SYSDB_INDEXES);
if (dn == NULL) {
ERROR_OUT(ret, EIO, done);
}

ldb_ret = ldb_search(ldb, mem_ctx, &res, dn, LDB_SCOPE_BASE, attrs, NULL);
if (ldb_ret != LDB_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, "ldb_search() failed: %i\n", ldb_ret);
ERROR_OUT(ret, EIO, done);
}
if (res->count != 1) {
DEBUG(SSSDBG_OP_FAILURE,
"ldb_search() returned %u messages. Expected 1.\n", res->count);
ERROR_OUT(ret, EIO, done);
}
if (res->msgs[0]->num_elements != 1) {
DEBUG(SSSDBG_OP_FAILURE,
"ldb_search() returned %u elements. Expected 1.\n",
res->msgs[0]->num_elements);
ERROR_OUT(ret, EIO, done);
}

el = res->msgs[0]->elements;
j = 0;
indexes = talloc_zero_array(mem_ctx, const char *, 1);
if (indexes == NULL) ERROR_OUT(ret, ENOMEM, done);

for (i = 0; i < el->num_values; i++) {
data = (char *) el->values[i].data;
length = (int) el->values[i].length;
if (attr_length == 0 ||
(attr_length == length && strncmp(attribute, data, length) == 0)) {
indexes = talloc_realloc(mem_ctx, indexes, const char *, j + 2);
if (indexes == NULL) ERROR_OUT(ret, ENOMEM, done);

indexes[j] = talloc_asprintf(indexes, "%*s", length, data);
if (indexes[j] == NULL) ERROR_OUT(ret, ENOMEM, done);

indexes[++j] = NULL;
}
}

*_indexes = indexes;
ret = EOK;

done:
talloc_free(dn);
if (ret != EOK) {
talloc_free(indexes);
}

return ret;
}

errno_t sysdb_ldb_mod_index(TALLOC_CTX *mem_ctx,
enum sysdb_index_actions action,
struct ldb_context *ldb,
const char *attribute)
{
errno_t ret;
int ldb_ret;
struct ldb_message *msg;

msg = ldb_msg_new(mem_ctx);
if (msg == NULL) {
ERROR_OUT(ret, ENOMEM, done);
}

msg->dn = ldb_dn_new(msg, ldb, SYSDB_INDEXES);
if (msg->dn == NULL) {
ERROR_OUT(ret, EIO, done);
}

if (action == SYSDB_IDX_CREATE) {
ldb_ret = sysdb_add_string(msg, SYSDB_IDXATTR, attribute);
} else if (action == SYSDB_IDX_DELETE) {
ldb_ret = sysdb_delete_string(msg, SYSDB_IDXATTR, attribute);
} else {
ERROR_OUT(ret, EINVAL, done);
}
if (ldb_ret != LDB_SUCCESS) {
ERROR_OUT(ret, EIO, done);
}

ldb_ret = sss_ldb_modify(ldb, msg, false);
if (ldb_ret != LDB_SUCCESS) {
switch (ldb_ret) {
case LDB_ERR_NO_SUCH_ATTRIBUTE:
ret = ENOENT;
break;
case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
ret = EEXIST;
break;
default:
ret = EIO;
}
goto done;
}

ret = EOK;

done:
talloc_free(msg);

return ret;
}

errno_t sysdb_manage_index(TALLOC_CTX *mem_ctx, enum sysdb_index_actions action,
const char *name, const char *attribute,
const char ***_indexes)
{
errno_t ret;
struct ldb_context *ldb = NULL;

ret = sysdb_ldb_connect(mem_ctx, name, LDB_FLG_DONT_CREATE_DB, &ldb);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_ldb_connect() failed.\n");
goto done;
}

switch (action) {
case SYSDB_IDX_CREATE:
case SYSDB_IDX_DELETE:
ret = sysdb_ldb_mod_index(ldb, action, ldb, attribute);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_ldb_mod_index() failed.\n");
goto done;
}
break;
case SYSDB_IDX_LIST:
ret = sysdb_ldb_list_indexes(mem_ctx, ldb, attribute, _indexes);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_ldb_list_indexes() failed.\n");
goto done;
}
break;
default:
DEBUG(SSSDBG_CRIT_FAILURE, "Unknown action: %i\n", action);
goto done;
}

done:
talloc_free(ldb);

return ret;
}

10 changes: 9 additions & 1 deletion src/db/sysdb_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,15 @@ errno_t sysdb_ldb_connect(TALLOC_CTX *mem_ctx,
const char *filename,
int flags,
struct ldb_context **_ldb);

errno_t sysdb_ldb_mod_index(TALLOC_CTX *mem_ctx,
enum sysdb_index_actions action,
struct ldb_context *ldb,
const char *attribute);
errno_t sysdb_manage_index(TALLOC_CTX *mem_ctx,
enum sysdb_index_actions action,
const char *name,
const char *attribute,
const char ***indexes);
struct sysdb_dom_upgrade_ctx {
struct sss_names_ctx *names; /* upgrade to 0.18 needs to parse names */
};
Expand Down
22 changes: 22 additions & 0 deletions src/tools/common/sss_tools.c
Original file line number Diff line number Diff line change
Expand Up @@ -578,3 +578,25 @@ errno_t sss_tool_parse_name(TALLOC_CTX *mem_ctx,

return ret;
}

errno_t sss_tool_connect_to_confdb(TALLOC_CTX *ctx, struct confdb_ctx **cdb_ctx)
{
int ret;
char *confdb_path = NULL;

confdb_path = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE);
if (confdb_path == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Could not allocate memory for confdb path\n");
return ENOMEM;
}

ret = confdb_init(ctx, cdb_ctx, confdb_path);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Could not initialize connection to the confdb\n");
}

talloc_free(confdb_path);
return ret;
}
3 changes: 3 additions & 0 deletions src/tools/common/sss_tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,7 @@ errno_t sss_tool_parse_name(TALLOC_CTX *mem_ctx,
const char **_username,
struct sss_domain_info **_domain);


errno_t sss_tool_connect_to_confdb(TALLOC_CTX *ctx, struct confdb_ctx **cdb_ctx);

#endif /* SRC_TOOLS_COMMON_SSS_TOOLS_H_ */
1 change: 1 addition & 0 deletions src/tools/sssctl/sssctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ int main(int argc, const char **argv)
SSS_TOOL_COMMAND("cache-remove", "Backup local data and remove cached content", 0, sssctl_cache_remove),
SSS_TOOL_COMMAND("cache-upgrade", "Perform cache upgrade", ERR_SYSDB_VERSION_TOO_OLD, sssctl_cache_upgrade),
SSS_TOOL_COMMAND("cache-expire", "Invalidate cached objects", 0, sssctl_cache_expire),
SSS_TOOL_COMMAND("cache-index", "Manage cache indexes", 0, sssctl_cache_index),
SSS_TOOL_DELIMITER("Log files tools:"),
SSS_TOOL_COMMAND("logs-remove", "Remove existing SSSD log files", 0, sssctl_logs_remove),
SSS_TOOL_COMMAND("logs-fetch", "Archive SSSD log files in tarball", 0, sssctl_logs_fetch),
Expand Down
4 changes: 4 additions & 0 deletions src/tools/sssctl/sssctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ errno_t sssctl_cache_expire(struct sss_cmdline *cmdline,
struct sss_tool_ctx *tool_ctx,
void *pvt);

errno_t sssctl_cache_index(struct sss_cmdline *cmdline,
struct sss_tool_ctx *tool_ctx,
void *pvt);

errno_t sssctl_logs_remove(struct sss_cmdline *cmdline,
struct sss_tool_ctx *tool_ctx,
void *pvt);
Expand Down

0 comments on commit 1421fa4

Please sign in to comment.