sssd/0088-SECRETS-Read-the-quota...

440 lines
15 KiB
Diff

From 4db56d8c90a6467a216590e5ba3bdcd2a2bf1ae9 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Tue, 30 May 2017 12:51:19 +0200
Subject: [PATCH 88/93] SECRETS: Read the quotas for cn=secrets from
[secrets/secrets] configuration subsection
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch makes obsoletes the old way of configuring quotas for the
secrets responder. Instead, adds a new way of configuring each hive
separately in a configuration subsection, e.g.
[secrets/secrets]
max_secrets = 123
The old way is still supported as a backwards-compatible method.
Reviewed-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
---
src/config/cfg_rules.ini | 10 +++
src/man/sssd-secrets.5.xml | 45 ++++++++++++-
src/responder/secrets/secsrv.c | 139 +++++++++++++++++++++++++++++++++--------
src/tests/intg/test_secrets.py | 125 +++++++++++++++++++++++++++---------
4 files changed, 262 insertions(+), 57 deletions(-)
diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
index ae60c73c871e1ac18a26124232e1f9f7c9f8fabb..a963eb49c9010924bda6a48c47d80c868ffd6ddd 100644
--- a/src/config/cfg_rules.ini
+++ b/src/config/cfg_rules.ini
@@ -12,6 +12,7 @@ section = secrets
section = kcm
section = session_recording
section_re = ^secrets/users/[0-9]\+$
+section_re = ^secrets/secrets$
section_re = ^domain/[^/\@]\+$
section_re = ^domain/[^/\@]\+/[^/\@]\+$
section_re = ^application/[^/\@]\+$
@@ -256,6 +257,15 @@ option = max_secrets
option = max_payload_size
option = responder_idle_timeout
+[rule/allowed_sec_hive_options]
+validator = ini_allowed_options
+section_re = ^secrets/secrets$
+
+# Secrets service - per-hive configuration
+option = containers_nest_level
+option = max_secrets
+option = max_payload_size
+
[rule/allowed_sec_users_options]
validator = ini_allowed_options
section_re = ^secrets/users/[0-9]\+$
diff --git a/src/man/sssd-secrets.5.xml b/src/man/sssd-secrets.5.xml
index 44a86c3fb56a8bdebebd01e9f49ad171986282a4..d50cb13d8a0dcbdb7919c1e38d6d5976dcc2abf1 100644
--- a/src/man/sssd-secrets.5.xml
+++ b/src/man/sssd-secrets.5.xml
@@ -57,6 +57,32 @@
collide between users. Secrets can be stored inside
<quote>containers</quote> which can be nested.
</para>
+ <para>
+ Since the secrets responder can be used both externally to store
+ general secrets, as described in the rest of this man page, but
+ also internally by other SSSD components to store their secret
+ material, some configuration options, like quotas can be configured
+ per <quote>hive</quote> in a configuration subsection named after
+ the hive. The currently supported hives are:
+ <variablelist>
+ <varlistentry>
+ <term>secrets</term>
+ <listitem><para>secrets for general usage</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>kcm</term>
+ <listitem>
+ <para>used by the
+ <citerefentry>
+ <refentrytitle>sssd-kcm</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>
+ service.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
</refsect1>
<refsect1 id='usage'>
@@ -144,6 +170,12 @@ systemctl enable sssd-secrets.service
</para>
</listitem>
</varlistentry>
+ </variablelist>
+ <para>
+ The following options affect only the secrets <quote>hive</quote>
+ and therefore should be set in a per-hive subsection.
+ </para>
+ <variablelist>
<varlistentry>
<term>containers_nest_level (integer)</term>
<listitem>
@@ -161,7 +193,7 @@ systemctl enable sssd-secrets.service
<listitem>
<para>
This option specifies the maximum number of secrets that
- can be stored.
+ can be stored in the hive.
</para>
<para>
Default: 1024
@@ -181,6 +213,17 @@ systemctl enable sssd-secrets.service
</listitem>
</varlistentry>
</variablelist>
+ <para>
+ For example, to adjust quotas differently for both the <quote>secrets</quote>
+ and the <quote>kcm</quote> hives, configure the following:
+ <programlisting>
+[secrets/secrets]
+max_payload_size = 128
+
+[secrets/kcm]
+max_payload_size = 256
+ </programlisting>
+ </para>
<para>
The following options are only applicable for configurations that
use the <quote>proxy</quote> provider.
diff --git a/src/responder/secrets/secsrv.c b/src/responder/secrets/secsrv.c
index e3a8c1476af8d9c2c8b87a11ca930e12f381ef94..db12cbbc3eb9317b6d449a5d2b2d370afebf247e 100644
--- a/src/responder/secrets/secsrv.c
+++ b/src/responder/secrets/secsrv.c
@@ -33,6 +33,100 @@
#define DEFAULT_SEC_MAX_SECRETS 1024
#define DEFAULT_SEC_MAX_PAYLOAD_SIZE 16
+static int sec_get_quota(struct sec_ctx *sctx,
+ const char *section_config_path,
+ int default_max_containers_nest_level,
+ int default_max_num_secrets,
+ int default_max_payload,
+ struct sec_quota *quota)
+{
+ int ret;
+
+ ret = confdb_get_int(sctx->rctx->cdb,
+ section_config_path,
+ CONFDB_SEC_CONTAINERS_NEST_LEVEL,
+ default_max_containers_nest_level,
+ &quota->containers_nest_level);
+
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ "Failed to get container nesting level for %s\n",
+ section_config_path);
+ return ret;
+ }
+
+ ret = confdb_get_int(sctx->rctx->cdb,
+ section_config_path,
+ CONFDB_SEC_MAX_SECRETS,
+ default_max_num_secrets,
+ &quota->max_secrets);
+
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ "Failed to get maximum number of entries for %s\n",
+ section_config_path);
+ return ret;
+ }
+
+ ret = confdb_get_int(sctx->rctx->cdb,
+ section_config_path,
+ CONFDB_SEC_MAX_PAYLOAD_SIZE,
+ default_max_payload,
+ &quota->max_payload_size);
+
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ "Failed to get payload's maximum size for an entry in %s\n",
+ section_config_path);
+ return ret;
+ }
+
+ return EOK;
+}
+
+static int sec_get_hive_config(struct sec_ctx *sctx,
+ const char *hive_name,
+ struct sec_hive_config *hive_config,
+ int default_max_containers_nest_level,
+ int default_max_num_secrets,
+ int default_max_payload)
+{
+ int ret;
+ TALLOC_CTX *tmp_ctx;
+
+ tmp_ctx = talloc_new(sctx);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ hive_config->confdb_section = talloc_asprintf(sctx,
+ "config/secrets/%s",
+ hive_name);
+ if (hive_config->confdb_section == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sec_get_quota(sctx,
+ hive_config->confdb_section,
+ default_max_containers_nest_level,
+ default_max_num_secrets,
+ default_max_payload,
+ &hive_config->quota);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Cannot read quota settings for %s [%d]: %s\n",
+ hive_name, ret, sss_strerror(ret));
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
static int sec_get_config(struct sec_ctx *sctx)
{
int ret;
@@ -48,39 +142,32 @@ static int sec_get_config(struct sec_ctx *sctx)
goto fail;
}
- ret = confdb_get_int(sctx->rctx->cdb,
- sctx->rctx->confdb_service_path,
- CONFDB_SEC_CONTAINERS_NEST_LEVEL,
- DEFAULT_SEC_CONTAINERS_NEST_LEVEL,
- &sctx->sec_config.quota.containers_nest_level);
-
- if (ret != EOK) {
- DEBUG(SSSDBG_FATAL_FAILURE,
- "Failed to get containers' maximum depth\n");
- goto fail;
- }
-
- ret = confdb_get_int(sctx->rctx->cdb,
- sctx->rctx->confdb_service_path,
- CONFDB_SEC_MAX_SECRETS,
- DEFAULT_SEC_MAX_SECRETS,
- &sctx->sec_config.quota.max_secrets);
-
+ /* Read the global quota first -- this should be removed in a future release */
+ /* Note that this sets the defaults for the sec_config quota to be used
+ * in sec_get_hive_config()
+ */
+ ret = sec_get_quota(sctx,
+ sctx->rctx->confdb_service_path,
+ DEFAULT_SEC_CONTAINERS_NEST_LEVEL,
+ DEFAULT_SEC_MAX_SECRETS,
+ DEFAULT_SEC_MAX_PAYLOAD_SIZE,
+ &sctx->sec_config.quota);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
- "Failed to get maximum number of entries\n");
+ "Failed to get legacy global quotas\n");
goto fail;
}
- ret = confdb_get_int(sctx->rctx->cdb,
- sctx->rctx->confdb_service_path,
- CONFDB_SEC_MAX_PAYLOAD_SIZE,
- DEFAULT_SEC_MAX_PAYLOAD_SIZE,
- &sctx->sec_config.quota.max_payload_size);
-
+ /* Read the per-hive configuration */
+ ret = sec_get_hive_config(sctx,
+ "secrets",
+ &sctx->sec_config,
+ sctx->sec_config.quota.containers_nest_level,
+ sctx->sec_config.quota.max_secrets,
+ sctx->sec_config.quota.max_payload_size);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
- "Failed to get payload's maximum size for an entry\n");
+ "Failed to get configuration of the secrets hive\n");
goto fail;
}
diff --git a/src/tests/intg/test_secrets.py b/src/tests/intg/test_secrets.py
index 32ea58ff017f01bc6a28f826d10dabff60761bcb..bb94ffb47666f964fae2764444f7d28f3b311145 100644
--- a/src/tests/intg/test_secrets.py
+++ b/src/tests/intg/test_secrets.py
@@ -169,36 +169,6 @@ def test_crd_ops(setup_for_secrets, secrets_cli):
cli.del_secret("foo")
assert str(err404.value).startswith("404")
- # Don't allow storing more secrets after reaching the max
- # number of entries.
- MAX_SECRETS = 10
-
- sec_value = "value"
- for x in range(MAX_SECRETS):
- cli.set_secret(str(x), sec_value)
-
- with pytest.raises(HTTPError) as err507:
- cli.set_secret(str(MAX_SECRETS), sec_value)
- assert str(err507.value).startswith("507")
-
- # Delete all stored secrets used for max secrets tests
- for x in range(MAX_SECRETS):
- cli.del_secret(str(x))
-
- # Don't allow storing a secrets which has a payload larger
- # than max_payload_size
- KILOBYTE = 1024
- MAX_PAYLOAD_SIZE = 2 * KILOBYTE
-
- sec_value = "x" * MAX_PAYLOAD_SIZE
-
- cli.set_secret("foo", sec_value)
-
- sec_value += "x"
- with pytest.raises(HTTPError) as err413:
- cli.set_secret("bar", sec_value)
- assert str(err413.value).startswith("413")
-
def run_curlwrap_tool(args, exp_http_code):
cmd = subprocess.Popen(args,
@@ -434,3 +404,98 @@ def test_idle_timeout(setup_for_cli_timeout_test):
nfds_post = get_num_fds(secpid)
assert nfds_pre == nfds_post
+
+
+def run_quota_test(cli, max_secrets, max_payload_size):
+ sec_value = "value"
+ for x in range(max_secrets):
+ cli.set_secret(str(x), sec_value)
+
+ with pytest.raises(HTTPError) as err507:
+ cli.set_secret(str(max_secrets), sec_value)
+ assert str(err507.value).startswith("507")
+
+ # Delete all stored secrets used for max secrets tests
+ for x in range(max_secrets):
+ cli.del_secret(str(x))
+
+ # Don't allow storing a secrets which has a payload larger
+ # than max_payload_size
+ KILOBYTE = 1024
+ kb_payload_size = max_payload_size * KILOBYTE
+
+ sec_value = "x" * kb_payload_size
+
+ cli.set_secret("foo", sec_value)
+
+ sec_value += "x"
+ with pytest.raises(HTTPError) as err413:
+ cli.set_secret("bar", sec_value)
+ assert str(err413.value).startswith("413")
+
+
+@pytest.fixture
+def setup_for_global_quota(request):
+ conf = unindent("""\
+ [sssd]
+ domains = local
+ services = nss
+
+ [domain/local]
+ id_provider = local
+
+ [secrets]
+ max_secrets = 10
+ max_payload_size = 2
+ """).format(**locals())
+
+ create_conf_fixture(request, conf)
+ create_sssd_secrets_fixture(request)
+ return None
+
+
+def test_global_quota(setup_for_global_quota, secrets_cli):
+ """
+ Test that the deprecated configuration of quotas in the global
+ secrets section is still supported
+ """
+ cli = secrets_cli
+
+ # Don't allow storing more secrets after reaching the max
+ # number of entries.
+ run_quota_test(cli, 10, 2)
+
+
+@pytest.fixture
+def setup_for_secrets_quota(request):
+ conf = unindent("""\
+ [sssd]
+ domains = local
+ services = nss
+
+ [domain/local]
+ id_provider = local
+
+ [secrets]
+ max_secrets = 5
+ max_payload_size = 1
+
+ [secrets/secrets]
+ max_secrets = 10
+ max_payload_size = 2
+ """).format(**locals())
+
+ create_conf_fixture(request, conf)
+ create_sssd_secrets_fixture(request)
+ return None
+
+
+def test_sec_quota(setup_for_secrets_quota, secrets_cli):
+ """
+ Test that the new secrets/secrets section takes precedence.
+ """
+ cli = secrets_cli
+
+ # Don't allow storing more secrets after reaching the max
+ # number of entries.
+ run_quota_test(cli, 10, 2)
--
2.14.1