319 lines
12 KiB
Diff
319 lines
12 KiB
Diff
|
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
|
||
|
|