sssd/0090-SECRETS-Use-separate-quotas-for-kcm-and-secrets-hive.patch

319 lines
12 KiB
Diff
Raw Normal View History

From 197da163943868216f704fb34031e7d5576e8aee Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Tue, 4 Apr 2017 15:33:38 +0200
Subject: [PATCH 90/93] SECRETS: Use separate quotas for /kcm and /secrets
hives
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This would differentiate between out-of-capacity errors for secrets and
for KCM as they are two independent trees as far as sssd-secrets is
concerned.
The quotas for /kcm are also different in their defaults. For the /secrets
hive, we presume a large amount of small secrets. For the /kcm hive, we
presume a small amount of large secrets, because the secret is a ccache
which contains multiple credentials.
The operations are also passed in a struct quota from the local request
context instead of local_context. The quota is assigned to the request
context when the hive is selected.
Reviewed-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
---
src/config/cfg_rules.ini | 3 ++-
src/man/sssd-secrets.5.xml | 4 ++--
src/responder/secrets/local.c | 46 ++++++++++++++++++++++++------------------
src/responder/secrets/secsrv.c | 20 ++++++++++++++++++
src/responder/secrets/secsrv.h | 1 +
5 files changed, 51 insertions(+), 23 deletions(-)
diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
index a963eb49c9010924bda6a48c47d80c868ffd6ddd..7590f1f5aa516c0af899371a1b7a826512469de3 100644
--- a/src/config/cfg_rules.ini
+++ b/src/config/cfg_rules.ini
@@ -13,6 +13,7 @@ section = kcm
section = session_recording
section_re = ^secrets/users/[0-9]\+$
section_re = ^secrets/secrets$
+section_re = ^secrets/kcm$
section_re = ^domain/[^/\@]\+$
section_re = ^domain/[^/\@]\+/[^/\@]\+$
section_re = ^application/[^/\@]\+$
@@ -259,7 +260,7 @@ option = responder_idle_timeout
[rule/allowed_sec_hive_options]
validator = ini_allowed_options
-section_re = ^secrets/secrets$
+section_re = ^secrets/\(secrets\|kcm\)$
# Secrets service - per-hive configuration
option = containers_nest_level
diff --git a/src/man/sssd-secrets.5.xml b/src/man/sssd-secrets.5.xml
index d50cb13d8a0dcbdb7919c1e38d6d5976dcc2abf1..ba77d623274237951de5d42bb8cff9f6d56f5fff 100644
--- a/src/man/sssd-secrets.5.xml
+++ b/src/man/sssd-secrets.5.xml
@@ -196,7 +196,7 @@ systemctl enable sssd-secrets.service
can be stored in the hive.
</para>
<para>
- Default: 1024
+ Default: 1024 (secrets hive), 256 (kcm hive)
</para>
</listitem>
</varlistentry>
@@ -208,7 +208,7 @@ systemctl enable sssd-secrets.service
a secret payload in kilobytes.
</para>
<para>
- Default: 16
+ Default: 16 (secrets hive), 65536 (64 MiB) (kcm hive)
</para>
</listitem>
</varlistentry>
diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c
index c833f1d27b42e4a453ac62d29d7649ff80200fba..58e70f8b6d00976ccc86d4fbf687417dd3c3c06a 100644
--- a/src/responder/secrets/local.c
+++ b/src/responder/secrets/local.c
@@ -36,6 +36,7 @@ struct local_context {
struct sec_data master_key;
struct sec_quota *quota_secrets;
+ struct sec_quota *quota_kcm;
};
static int local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
@@ -206,7 +207,9 @@ static char *local_dn_to_path(TALLOC_CTX *mem_ctx,
struct local_db_req {
char *path;
+ const char *basedn;
struct ldb_dn *req_dn;
+ struct sec_quota *quota;
};
#define LOCAL_SIMPLE_FILTER "(type=simple)"
@@ -389,7 +392,7 @@ done:
return ret;
}
-static int local_db_check_containers_nest_level(struct local_context *lctx,
+static int local_db_check_containers_nest_level(struct local_db_req *lc_req,
struct ldb_dn *leaf_dn)
{
int nest_level;
@@ -397,11 +400,11 @@ static int local_db_check_containers_nest_level(struct local_context *lctx,
/* We need do not care for the synthetic containers that constitute the
* base path (cn=<uidnumber>,cn=user,cn=secrets). */
nest_level = ldb_dn_get_comp_num(leaf_dn) - 3;
- if (nest_level > lctx->quota_secrets->containers_nest_level) {
+ if (nest_level > lc_req->quota->containers_nest_level) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannot create a nested container of depth %d as the maximum"
"allowed number of nested containers is %d.\n",
- nest_level, lctx->quota_secrets->containers_nest_level);
+ nest_level, lc_req->quota->containers_nest_level);
return ERR_SEC_INVALID_CONTAINERS_NEST_LEVEL;
}
@@ -410,7 +413,8 @@ static int local_db_check_containers_nest_level(struct local_context *lctx,
}
static int local_db_check_number_of_secrets(TALLOC_CTX *mem_ctx,
- struct local_context *lctx)
+ struct local_context *lctx,
+ struct local_db_req *lc_req)
{
TALLOC_CTX *tmp_ctx;
static const char *attrs[] = { NULL };
@@ -421,7 +425,7 @@ static int local_db_check_number_of_secrets(TALLOC_CTX *mem_ctx,
tmp_ctx = talloc_new(mem_ctx);
if (!tmp_ctx) return ENOMEM;
- dn = ldb_dn_new(tmp_ctx, lctx->ldb, "cn=secrets");
+ dn = ldb_dn_new(tmp_ctx, lctx->ldb, lc_req->basedn);
if (!dn) {
ret = ENOMEM;
goto done;
@@ -429,11 +433,10 @@ static int local_db_check_number_of_secrets(TALLOC_CTX *mem_ctx,
ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_SUBTREE,
attrs, LOCAL_SIMPLE_FILTER);
- if (res->count >= lctx->quota_secrets->max_secrets) {
+ if (res->count >= lc_req->quota->max_secrets) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannot store any more secrets as the maximum allowed limit (%d) "
- "has been reached\n", lctx->quota_secrets->max_secrets);
-
+ "has been reached\n", lc_req->quota->max_secrets);
ret = ERR_SEC_INVALID_TOO_MANY_SECRETS;
goto done;
}
@@ -445,19 +448,19 @@ done:
return ret;
}
-static int local_check_max_payload_size(struct local_context *lctx,
+static int local_check_max_payload_size(struct local_db_req *lc_req,
int payload_size)
{
int max_payload_size;
- max_payload_size = lctx->quota_secrets->max_payload_size * 1024; /* kb */
+ max_payload_size = lc_req->quota->max_payload_size * 1024; /* kb */
if (payload_size > max_payload_size) {
DEBUG(SSSDBG_OP_FAILURE,
"Secrets' payload size [%d kb (%d)] exceeds the maximum allowed "
"payload size [%d kb (%d)]\n",
payload_size * 1024, /* kb */
payload_size,
- lctx->quota_secrets->max_payload_size, /* kb */
+ lc_req->quota->max_payload_size, /* kb */
max_payload_size);
return ERR_SEC_PAYLOAD_SIZE_IS_TOO_LARGE;
@@ -494,7 +497,7 @@ static int local_db_put_simple(TALLOC_CTX *mem_ctx,
goto done;
}
- ret = local_db_check_number_of_secrets(msg, lctx);
+ ret = local_db_check_number_of_secrets(msg, lctx, lc_req);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"local_db_check_number_of_secrets failed [%d]: %s\n",
@@ -502,7 +505,7 @@ static int local_db_put_simple(TALLOC_CTX *mem_ctx,
goto done;
}
- ret = local_check_max_payload_size(lctx, strlen(secret));
+ ret = local_check_max_payload_size(lc_req, strlen(secret));
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"local_check_max_payload_size failed [%d]: %s\n",
@@ -656,7 +659,7 @@ static int local_db_create(TALLOC_CTX *mem_ctx,
goto done;
}
- ret = local_db_check_containers_nest_level(lctx, msg->dn);
+ ret = local_db_check_containers_nest_level(lc_req, msg->dn);
if (ret != EOK) goto done;
ret = ldb_msg_add_string(msg, "type", "container");
@@ -698,13 +701,13 @@ done:
}
static int local_secrets_map_path(TALLOC_CTX *mem_ctx,
- struct ldb_context *ldb,
+ struct local_context *lctx,
struct sec_req_ctx *secreq,
struct local_db_req **_lc_req)
{
int ret;
struct local_db_req *lc_req;
- const char *basedn;
+ struct ldb_context *ldb = lctx->ldb;
/* be strict for now */
if (secreq->parsed_url.fragment != NULL) {
@@ -742,12 +745,14 @@ static int local_secrets_map_path(TALLOC_CTX *mem_ctx,
SEC_BASEPATH, sizeof(SEC_BASEPATH) - 1) == 0) {
lc_req->path = talloc_strdup(lc_req,
secreq->mapped_path + (sizeof(SEC_BASEPATH) - 1));
- basedn = SECRETS_BASEDN;
+ lc_req->basedn = SECRETS_BASEDN;
+ lc_req->quota = lctx->quota_secrets;
} else if (strncmp(secreq->mapped_path,
SEC_KCM_BASEPATH, sizeof(SEC_KCM_BASEPATH) - 1) == 0) {
lc_req->path = talloc_strdup(lc_req,
secreq->mapped_path + (sizeof(SEC_KCM_BASEPATH) - 1));
- basedn = KCM_BASEDN;
+ lc_req->basedn = KCM_BASEDN;
+ lc_req->quota = lctx->quota_kcm;
} else {
ret = EINVAL;
goto done;
@@ -760,7 +765,7 @@ static int local_secrets_map_path(TALLOC_CTX *mem_ctx,
goto done;
}
- ret = local_db_dn(mem_ctx, ldb, basedn, lc_req->path, &lc_req->req_dn);
+ ret = local_db_dn(mem_ctx, ldb, lc_req->basedn, lc_req->path, &lc_req->req_dn);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to map request to local db DN\n");
@@ -829,7 +834,7 @@ static struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
}
DEBUG(SSSDBG_TRACE_LIBS, "Content-Type: %s\n", content_type);
- ret = local_secrets_map_path(state, lctx->ldb, secreq, &lc_req);
+ ret = local_secrets_map_path(state, lctx, secreq, &lc_req);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE, "Cannot map request path to local path\n");
goto done;
@@ -1019,6 +1024,7 @@ int local_secrets_provider_handle(struct sec_ctx *sctx,
}
lctx->quota_secrets = &sctx->sec_config.quota;
+ lctx->quota_kcm = &sctx->kcm_config.quota;
lctx->master_key.data = talloc_size(lctx, MKEY_SIZE);
if (!lctx->master_key.data) return ENOMEM;
diff --git a/src/responder/secrets/secsrv.c b/src/responder/secrets/secsrv.c
index db12cbbc3eb9317b6d449a5d2b2d370afebf247e..2fcdf8e6c74eaccc75f1017efdc854fa065baf74 100644
--- a/src/responder/secrets/secsrv.c
+++ b/src/responder/secrets/secsrv.c
@@ -30,9 +30,17 @@
#define DEFAULT_SEC_FD_LIMIT 2048
#define DEFAULT_SEC_CONTAINERS_NEST_LEVEL 4
+
#define DEFAULT_SEC_MAX_SECRETS 1024
#define DEFAULT_SEC_MAX_PAYLOAD_SIZE 16
+/* The number of secrets in the /kcm hive should be quite small,
+ * but the secret size must be large because one secret in the /kcm
+ * hive holds the whole ccache which consists of several credentials
+ */
+#define DEFAULT_SEC_KCM_MAX_SECRETS 256
+#define DEFAULT_SEC_KCM_MAX_PAYLOAD_SIZE 65536
+
static int sec_get_quota(struct sec_ctx *sctx,
const char *section_config_path,
int default_max_containers_nest_level,
@@ -171,6 +179,18 @@ static int sec_get_config(struct sec_ctx *sctx)
goto fail;
}
+ ret = sec_get_hive_config(sctx,
+ "kcm",
+ &sctx->kcm_config,
+ DEFAULT_SEC_CONTAINERS_NEST_LEVEL,
+ DEFAULT_SEC_KCM_MAX_SECRETS,
+ DEFAULT_SEC_KCM_MAX_PAYLOAD_SIZE);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ "Failed to get configuration of the secrets hive\n");
+ goto fail;
+ }
+
ret = confdb_get_int(sctx->rctx->cdb, sctx->rctx->confdb_service_path,
CONFDB_RESPONDER_CLI_IDLE_TIMEOUT,
CONFDB_RESPONDER_CLI_IDLE_DEFAULT_TIMEOUT,
diff --git a/src/responder/secrets/secsrv.h b/src/responder/secrets/secsrv.h
index 629b027f6966dd221d21d16ccfc75c99881935f8..afc092764d02671eaf2cadd6a0f2f168ba7da806 100644
--- a/src/responder/secrets/secsrv.h
+++ b/src/responder/secrets/secsrv.h
@@ -47,6 +47,7 @@ struct sec_ctx {
int fd_limit;
struct sec_hive_config sec_config;
+ struct sec_hive_config kcm_config;
struct provider_handle **providers;
};
--
2.14.1