URL: https://github.com/SSSD/sssd/pull/33 Author: fidencio Title: #33: SECRETS: Some small misc fixes + fixing #3168 Action: synchronized
To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/33/head:pr33 git checkout pr33
From bc16e9d251916291056625f03781e996880494d7 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek <jhro...@redhat.com> Date: Mon, 8 Aug 2016 17:48:51 +0200 Subject: [PATCH 1/7] MAN: sssd-secrets documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents the API and the purpose of the sssd-secrets responder. Resolves: https://fedorahosted.org/sssd/ticket/3053 Acked-by: Fabiano Fidêncio <fiden...@redhat.com> --- contrib/sssd.spec.in | 1 + src/man/Makefile.am | 9 +- src/man/po/po4a.cfg | 1 + src/man/sssd-secrets.5.xml | 446 +++++++++++++++++++++++++++++++ src/sysv/systemd/sssd-secrets.service.in | 1 + src/sysv/systemd/sssd-secrets.socket.in | 1 + 6 files changed, 458 insertions(+), 1 deletion(-) create mode 100644 src/man/sssd-secrets.5.xml diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in index a0937d5..40e4454 100644 --- a/contrib/sssd.spec.in +++ b/contrib/sssd.spec.in @@ -868,6 +868,7 @@ done %{_mandir}/man5/sssd.conf.5* %{_mandir}/man5/sssd-simple.5* %{_mandir}/man5/sssd-sudo.5* +%{_mandir}/man5/sssd-secrets.5* %{_mandir}/man5/sss_rpcidmapd.5* %{_mandir}/man8/sssd.8* %{_mandir}/man8/sss_cache.8* diff --git a/src/man/Makefile.am b/src/man/Makefile.am index cd23b02..5e41d3a 100644 --- a/src/man/Makefile.am +++ b/src/man/Makefile.am @@ -24,12 +24,15 @@ endif if BUILD_IFP IFP_CONDS = ;with_ifp endif +if BUILD_SECRETS +SEC_CONDS = ;with_secrets +endif if GPO_DEFAULT_ENFORCING GPO_CONDS = ;gpo_default_enforcing else GPO_CONDS = ;gpo_default_permissive endif -CONDS = with_false$(SUDO_CONDS)$(AUTOFS_CONDS)$(SSH_CONDS)$(PAC_RESPONDER_CONDS)$(IFP_CONDS)$(GPO_CONDS) +CONDS = with_false$(SUDO_CONDS)$(AUTOFS_CONDS)$(SSH_CONDS)$(PAC_RESPONDER_CONDS)$(IFP_CONDS)$(GPO_CONDS)$(SEC_CONDS) #Special Rules: @@ -70,6 +73,10 @@ if BUILD_IFP man_MANS += sssd-ifp.5 endif +if BUILD_SECRETS +man_MANS += sssd-secrets.5 +endif + if BUILD_NFS_IDMAP man_MANS += sss_rpcidmapd.5 endif diff --git a/src/man/po/po4a.cfg b/src/man/po/po4a.cfg index 0dcc802..515c1c3 100644 --- a/src/man/po/po4a.cfg +++ b/src/man/po/po4a.cfg @@ -28,6 +28,7 @@ [type:docbook] sss_ssh_knownhostsproxy.1.xml $lang:$(builddir)/$lang/sss_ssh_knownhostsproxy.1.xml [type:docbook] idmap_sss.8.xml $lang:$(builddir)/$lang/idmap_sss.8.xml [type:docbook] sssctl.8.xml $lang:$(builddir)/$lang/sssctl.8.xml +[type:docbook] sssd-secrets.5.xml $lang:$(builddir)/$lang/sssd-secrets.5.xml [type:docbook] include/service_discovery.xml $lang:$(builddir)/$lang/include/service_discovery.xml opt:"-k 0" [type:docbook] include/upstream.xml $lang:$(builddir)/$lang/include/upstream.xml opt:"-k 0" [type:docbook] include/failover.xml $lang:$(builddir)/$lang/include/failover.xml opt:"-k 0" diff --git a/src/man/sssd-secrets.5.xml b/src/man/sssd-secrets.5.xml new file mode 100644 index 0000000..71a79f5 --- /dev/null +++ b/src/man/sssd-secrets.5.xml @@ -0,0 +1,446 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V4.4//EN" +"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> +<reference> +<title>SSSD Manual pages</title> +<refentry> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/upstream.xml" /> + + <refmeta> + <refentrytitle>sssd-secrets</refentrytitle> + <manvolnum>5</manvolnum> + <refmiscinfo class="manual">File Formats and Conventions</refmiscinfo> + </refmeta> + + <refnamediv id='name'> + <refname>sssd-secrets</refname> + <refpurpose>SSSD Secrets responder</refpurpose> + </refnamediv> + + <refsect1 id='description'> + <title>DESCRIPTION</title> + <para> + This manual page describes the configuration of the Secrets responder + for + <citerefentry> + <refentrytitle>sssd</refentrytitle> + <manvolnum>8</manvolnum> + </citerefentry>. + For a detailed syntax reference, refer to the <quote>FILE FORMAT</quote> section of the + <citerefentry> + <refentrytitle>sssd.conf</refentrytitle> + <manvolnum>5</manvolnum> + </citerefentry> manual page. + </para> + <para> + Many system and user applications need to store private + information such as passwords or service keys and have no good + way to properly deal with them. The simple approach is to embed + these <quote>secrets</quote> into configuration files + potentially ending up exposing sensitive key material to + backups, config management system and in general making it + harder to secure data. + </para> + <para> + The <ulink url="https://github.com/latchset/custodia">custodia</ulink> + project was born to deal with this problem in cloud like + environments, but we found the idea compelling even at a + single system level. As a security service, SSSD is ideal to + host this capability while offering the same API via a Unix + Socket. This will make it possible to use local calls and have + them transparently routed to a local or a remote key management + store like IPA Vault for storage, escrow and recovery. + </para> + <para> + The secrets are simple key-value pairs. Each user's secrets are + namespaced using their user ID, which means the secrets will never + collide between users. Secrets can be stored inside + <quote>containers</quote> which can be nested. + </para> + </refsect1> + + <refsect1 id='usage'> + <title>USING THE SECRETS RESPONDER</title> + <para> + The UNIX socket the SSSD responder listens on is located at + <filename>/var/run/secrets.socket</filename>. + </para> + <para> + The secrets responder is socket-activated by + <citerefentry> + <refentrytitle>systemd</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>. + Unlike + other SSSD responders, it cannot be started by adding the + <quote>secrets</quote> string to the <quote>service</quote> + directive. + The systemd socket unit is called + <quote>sssd-secrets.socket</quote> and the corresponding service + file is called <quote>sssd-secrets.service</quote>. In order + for the service to be socket-activated, make sure the socket + is enabled and active and the service is enabled: + <programlisting> +systemctl start sssd-secrets.socket +systemctl enable sssd-secrets.socket +systemctl enable sssd-secrets.service + </programlisting> + Please note your distribution may already configure the units + for you. + </para> + </refsect1> + + <refsect1 id='options'> + <title>CONFIGURATION OPTIONS</title> + <para> + The generic SSSD responder options such as + <quote>debug_level</quote> or <quote>fd_limit</quote> are + accepted by the secrets responder. Please refer to the + <citerefentry> + <refentrytitle>sssd.conf</refentrytitle> + <manvolnum>5</manvolnum> + </citerefentry> manual page for a complete list. In addition, + there are some secrets-specific options as well. + </para> + <variablelist> + <varlistentry> + <term>provider (string)</term> + <listitem> + <para> + This option specifies where should the secrets + be stored. The secrets responder can configure a + per-user subsections that define which provider store + the secrets for this particular user. The per-user + subsections should contain all options for that user's + provider. If a per-user section does not exist, the + global settings from the secret responder's section + are used. The following providers are supported: + <variablelist> + <varlistentry> + <term>local</term> + <listitem> + <para> + The secrets are stored in a local database, + encrypted at rest with a master key. The local + provider does not have any additional config options + at the moment. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>proxy</term> + <listitem> + <para> + The secrets responder forwards the requests to + a Custodia server. The proxy provider supports + several additional options (see below). + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + <para> + Default: local + </para> + </listitem> + </varlistentry> + </variablelist> + <para> + The following options are only applicable for configurations that + use the <quote>proxy</quote> provider. + </para> + <variablelist> + <varlistentry> + <term>proxy_url (string)</term> + <listitem> + <para> + The URL the Custodia server is listening on. At the moment, + http and https protocols are supported. + </para> + <para> + The format of the URI must match the format defined in RFC 2732: + </para> + <para> + http[s]://<host>[:port] + </para> + <para> + Example: http://localhost:8080 + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>auth_type (string)</term> + <listitem> + <para> + The method to use when authenticating to a Custodia server. The + following authentication methods are supported: + </para> + <variablelist> + <varlistentry> + <term>basic_auth</term> + <listitem> + <para> + Authenticate with a username and a password as set + in the <quote>username</quote> and + <quote>password</quote> options. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>header</term> + <listitem> + <para> + Authenticate with HTTP header value as defined in + the <quote>auth_header_name</quote> and + <quote>auth_header_value</quote> + configuration options. + </para> + </listitem> + </varlistentry> + </variablelist> + </listitem> + </varlistentry> + <varlistentry> + <term>auth_header_name (string)</term> + <listitem> + <para> + If set, the secrets responder would put a header with this name + into the HTTP request with the value defined in the + <quote>auth_header_value</quote> configuration option. + </para> + <para> + Example: MYSECRETNAME + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>auth_header_value (string)</term> + <listitem> + <para> + The value sssd-secrets would use for the + <quote>auth_header_name</quote>. + </para> + <para> + Example: mysecret + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>forward_headers (list of strings)</term> + <listitem> + <para> + The list of HTTP headers to forward to the Custodia server + together with the request. + </para> + <para> + Default: not set + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + <refsect1 id='restapi'> + <title>USING THE REST API</title> + <para> + This section lists the available commands and includes examples using the + <citerefentry> + <refentrytitle>curl</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry> utility. + All requests towards the proxy provider must set the Content + Type header to <quote>application/json</quote>. In addition, + the local provider also supports Content Type set to + <quote>application/octet-stream</quote>. + Secrets stored with requests that set the Content Type header + to <quote>application/octet-stream</quote> are base64-encoded + when stored and decoded when retrieved, so it's not possible to + store a secret with one Content Type and retrieve with another. + The secret URI must begin with <filename>/secrets/</filename>. + </para> + <variablelist> + <varlistentry> + <term>Listing secrets</term> + <listitem> + <para> + To list the available secrets, send a HTTP GET request + with a trailing slash appended to the container path. + </para> + <para> + Example: + <programlisting> +curl -H "Content-Type: application/json" \ + --unix-socket /var/run/secrets.socket \ + -XGET http://localhost/secrets/ + </programlisting> + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>Retrieving a secret</term> + <listitem> + <para> + To read a value of a single secret, send a HTTP GET request + without a trailing slash. The last portion of the URI is the name + of the secret. + </para> + <para> + Examples: + <programlisting> +curl -H "Content-Type: application/json" \ + --unix-socket /var/run/secrets.socket \ + -XGET http://localhost/secrets/foo + </programlisting> + <programlisting> +curl -H "Content-Type: application/octet-stream" \ + --unix-socket /var/run/secrets.socket \ + -XGET http://localhost/secrets/bar + </programlisting> + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>Setting a secret</term> + <listitem> + <para> + To set a secret using the <quote>application/json</quote> + type, send a HTTP PUT request with a + JSON payload that includes type and value. The type + should be set to "simple" and the value should be + set to the secret value. If a secret with that name + already exists, the response is a 409 HTTP error. + </para> + <para> + The <quote>application/json</quote> type just sends + the secret as the message payload. + </para> + <para> + The following example sets a secret named 'foo' + to a value of 'foosecret' and a secret named 'bar' + to a value of 'barsecret' using a different + Content Type. + <programlisting> +curl -H "Content-Type: application/json" \ + --unix-socket /var/run/secrets.socket \ + -XPUT http://localhost/secrets/foo \ + -d'{"type":"simple","value":"foosecret"}' + </programlisting> + <programlisting> +curl -H "Content-Type: application/octet-stream" \ + --unix-socket /var/run/secrets.socket \ + -XPUT http://localhost/secrets/bar \ + -d'barsecret' + </programlisting> + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>Creating a container</term> + <listitem> + <para> + Containers provide an additional namespace for + this user's secrets. To create a container, send + a HTTP POST request, whose URI ends with the + container name. Please note the URI must end with + a trailing slash. + </para> + <para> + The following example creates a container named + 'mycontainer': + <programlisting> +curl -H "Content-Type: application/json" \ + --unix-socket /var/run/secrets.socket \ + -XPOST http://localhost/secrets/mycontainer/ + </programlisting> + </para> + <para> + To manipulate secrets under this container, just nest the + secrets underneath the container path: + <programlisting> +http://localhost/secrets/mycontainer/mysecret + </programlisting> + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>Deleting a secret or a container</term> + <listitem> + <para> + To delete a secret or a container, send a HTTP DELETE + request with a path to the secret or the container. + </para> + <para> + The following example deletes a secret named 'foo'. + <programlisting> +curl -H "Content-Type: application/json" \ + --unix-socket /var/run/secrets.socket \ + -XDELETE http://localhost/secrets/foo + </programlisting> + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + <refsect1 id='custodia_example'> + <title>EXAMPLE CUSTODIA AND PROXY PROVIDER CONFIGURATION</title> + <para> + For testing the proxy provider, you need to set up a Custodia server + to proxy requests to. Please always consult the Custodia documentation, + the configuration directives might change with different Custodia versions. + </para> + <para> + This configuration will set up a Custodia server listening on + http://localhost:8080, allowing anyone with header named MYSECRETNAME + set to mysecretkey to communicate with the Custodia server. + Place the contents into a file (for example, + <replaceable>custodia.conf</replaceable>): + <programlisting> +[global] +server_version = "Secret/0.0.7" +server_url = http://localhost:8080/ +auditlog = /var/log/custodia.log +debug = True + +[store:simple] +handler = custodia.store.sqlite.SqliteStore +dburi = /var/lib/custodia.db +table = secrets + +[auth:header] +handler = custodia.httpd.authenticators.SimpleHeaderAuth +header = MYSECRETNAME +value = mysecretkey + +[authz:paths] +handler = custodia.httpd.authorizers.SimplePathAuthz +paths = /secrets + +[/] +handler = custodia.root.Root +store = simple + </programlisting> + </para> + <para> + Then run the <replaceable>custodia</replaceable> command, pointing it + at the config file as a command line argument. + </para> + <para> + Please note that currently it's not possible to proxy all + requests globally to a Custodia instance. Instead, per-user + subsections for user IDs that should proxy requests to Custodia + must be defined. The following example illustrates a configuration, + where the user with UID 123 would proxy their requests to Custodia, + but all other user's requests would be handled by a local provider. + </para> + <programlisting> +[secrets] + +[secrets/users/123] +provider = proxy +proxy_url = http://localhost:8080/secrets/ +auth_type = header +auth_header_name = MYSECRETNAME +auth_header_value = mysecretkey + </programlisting> + </refsect1> +</refentry> +</reference> diff --git a/src/sysv/systemd/sssd-secrets.service.in b/src/sysv/systemd/sssd-secrets.service.in index 119c9bb..f45d647 100644 --- a/src/sysv/systemd/sssd-secrets.service.in +++ b/src/sysv/systemd/sssd-secrets.service.in @@ -1,5 +1,6 @@ [Unit] Description=SSSD Secrets Service responder +Documentation=man:sssd-secrets(5) [Install] Also=sssd-secrets.socket diff --git a/src/sysv/systemd/sssd-secrets.socket.in b/src/sysv/systemd/sssd-secrets.socket.in index 682e8f6..fb64852 100644 --- a/src/sysv/systemd/sssd-secrets.socket.in +++ b/src/sysv/systemd/sssd-secrets.socket.in @@ -1,5 +1,6 @@ [Unit] Description=SSSD Secrets Service responder socket +Documentation=man:sssd-secrets(5) [Socket] ListenStream=@localstatedir@/run/secrets.socket From 6924a48cc6720d7bc4c1a0648f83a1b082323b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fiden...@redhat.com> Date: Sun, 25 Sep 2016 20:49:16 +0200 Subject: [PATCH 2/7] CONFIG: Add secrets responder to the allowed sections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related: https://fedorahosted.org/sssd/ticket/3207 Signed-off-by: Fabiano Fidêncio <fiden...@redhat.com> --- src/config/cfg_rules.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini index 01be0c6..597389e 100644 --- a/src/config/cfg_rules.ini +++ b/src/config/cfg_rules.ini @@ -8,6 +8,7 @@ section = autofs section = ssh section = pac section = ifp +section_re = ^secrets[/0-9+]?$ section_re = ^domain/.*$ [rule/allowed_sssd_options] From b103f184cca45c38189ec5f361c4472d4f544402 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek <jhro...@redhat.com> Date: Tue, 16 Aug 2016 21:15:28 +0200 Subject: [PATCH 3/7] CONFIG: List allowed secrets responder options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related: https://fedorahosted.org/sssd/ticket/3207 Signed-off-by: Fabiano Fidêncio <fiden...@redhat.com> --- src/config/cfg_rules.ini | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini index 597389e..1ee98e5 100644 --- a/src/config/cfg_rules.ini +++ b/src/config/cfg_rules.ini @@ -210,6 +210,33 @@ option = description option = allowed_uids option = user_attributes +[rule/allowed_sec_options] +validator = ini_allowed_options +section_re = ^secrets[/0-9+]?$ + +option = timeout +option = debug +option = debug_level +option = debug_timestamps +option = debug_microseconds +option = debug_to_files +option = command +option = reconnection_retries +option = fd_limit +option = client_idle_timeout +option = description + +# Secrets service +option = provider +# Secrets service - proxy +option = proxy_url +option = auth_type +option = auth_header_name +option = auth_header_value +option = forward_headers +option = username +option = password + [rule/allowed_domain_options] validator = ini_allowed_options section_re = ^domain/.*$ From 52803f9f2007ffcebecf2c07fc08171b3c1e7673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fiden...@redhat.com> Date: Sun, 25 Sep 2016 21:52:10 +0200 Subject: [PATCH 4/7] CONFIG: Add secrets provider options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related: https://fedorahosted.org/sssd/ticket/3207 Signed-off-by: Fabiano Fidêncio <fiden...@redhat.com> --- src/config/SSSDConfig/__init__.py.in | 11 +++++++++++ src/config/SSSDConfigTest.py | 6 ++++-- src/config/etc/sssd.api.conf | 12 ++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index e616ce3..15b9cd1 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -118,6 +118,17 @@ option_strings = { 'allowed_uids': _('List of UIDs or user names allowed to access the InfoPipe responder'), 'user_attributes': _('List of user attributes the InfoPipe is allowed to publish'), + # [secrets] + 'provider': _('The provider where the secrets will be stored in'), + # secrets - proxy + 'proxy_url': _('The URL Custodia server is listening on'), + 'auth_type': _('The method to use when authenticating to a Custodia server'), + 'auth_header_name': _('The name of the headers that will be added into a HTTP request with the value defined in auth_header_value'), + 'auth_header_value': _('The value sssd-secrets would use for auth_header_name'), + 'forward_headers': _('The list of the headers to forward to the Custodia server together with the request'), + 'username': _('The username to use when authenticating to a Custodia server using basic_auth'), + 'password': _('The password to use when authenticating to a Custodia server using basic_auth'), + # [provider] 'id_provider' : _('Identity provider'), 'auth_provider' : _('Authentication provider'), diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py index 006a034..4850073 100755 --- a/src/config/SSSDConfigTest.py +++ b/src/config/SSSDConfigTest.py @@ -1352,7 +1352,8 @@ def testNewConfig(self): 'autofs', 'ssh', 'pac', - 'ifp'] + 'ifp', + 'secrets'] for section in control_list: self.assertTrue(sssdconfig.has_section(section), "Section [%s] missing" % @@ -1445,7 +1446,8 @@ def testListServices(self): 'autofs', 'ssh', 'pac', - 'ifp'] + 'ifp', + 'secrets'] service_list = sssdconfig.list_services() for service in control_list: self.assertTrue(service in service_list, diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf index 9e4bf2f..f94c8d1 100644 --- a/src/config/etc/sssd.api.conf +++ b/src/config/etc/sssd.api.conf @@ -94,6 +94,18 @@ pac_lifetime = int, None, false allowed_uids = str, None, false user_attributes = str, None, false +[secrets] +# Secrets service +provider = str, None, false +# Secrets service - proxy +proxy_url = str, None, false +auth_type = str, None, false +auth_header_name = str, None, false +auth_header_value = str, None, false +forward_headers = list, None, false +username = str, None, false +password = str, None, false + [provider] #Available provider types id_provider = str, None, true From 1fff3753bf54c42fdf78675a8411231ab509b158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fiden...@redhat.com> Date: Mon, 26 Sep 2016 01:07:31 +0200 Subject: [PATCH 5/7] SECRETS: Make functions from local.c static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no reason for those functions to be exposed. Signed-off-by: Fabiano Fidêncio <fiden...@redhat.com> --- src/responder/secrets/local.c | 86 +++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c index b13e77f..0ce0526 100644 --- a/src/responder/secrets/local.c +++ b/src/responder/secrets/local.c @@ -31,9 +31,9 @@ struct local_context { struct sec_data master_key; }; -int local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx, - const char *secret, const char *enctype, - char **plain_secret) +static int local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx, + const char *secret, const char *enctype, + char **plain_secret) { char *output; @@ -66,9 +66,9 @@ int local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx, return EOK; } -int local_encrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx, - const char *secret, const char *enctype, - char **ciphertext) +static int local_encrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx, + const char *secret, const char *enctype, + char **ciphertext) { struct sec_data _secret; char *output; @@ -91,10 +91,10 @@ int local_encrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx, return EOK; } -int local_db_dn(TALLOC_CTX *mem_ctx, - struct ldb_context *ldb, - const char *req_path, - struct ldb_dn **req_dn) +static int local_db_dn(TALLOC_CTX *mem_ctx, + struct ldb_context *ldb, + const char *req_path, + struct ldb_dn **req_dn) { struct ldb_dn *dn; const char *s, *e; @@ -136,9 +136,9 @@ int local_db_dn(TALLOC_CTX *mem_ctx, return ret; } -char *local_dn_to_path(TALLOC_CTX *mem_ctx, - struct ldb_dn *basedn, - struct ldb_dn *dn) +static char *local_dn_to_path(TALLOC_CTX *mem_ctx, + struct ldb_dn *basedn, + struct ldb_dn *dn) { int basecomps; int dncomps; @@ -170,10 +170,10 @@ char *local_dn_to_path(TALLOC_CTX *mem_ctx, #define LOCAL_SIMPLE_FILTER "(type=simple)" #define LOCAL_CONTAINER_FILTER "(type=container)" -int local_db_get_simple(TALLOC_CTX *mem_ctx, - struct local_context *lctx, - const char *req_path, - char **secret) +static int local_db_get_simple(TALLOC_CTX *mem_ctx, + struct local_context *lctx, + const char *req_path, + char **secret) { TALLOC_CTX *tmp_ctx; static const char *attrs[] = { "secret", "enctype", NULL }; @@ -228,11 +228,11 @@ int local_db_get_simple(TALLOC_CTX *mem_ctx, return ret; } -int local_db_list_keys(TALLOC_CTX *mem_ctx, - struct local_context *lctx, - const char *req_path, - char ***_keys, - int *num_keys) +static int local_db_list_keys(TALLOC_CTX *mem_ctx, + struct local_context *lctx, + const char *req_path, + char ***_keys, + int *num_keys) { TALLOC_CTX *tmp_ctx; static const char *attrs[] = { "secret", NULL }; @@ -282,9 +282,9 @@ int local_db_list_keys(TALLOC_CTX *mem_ctx, return ret; } -int local_db_check_containers(TALLOC_CTX *mem_ctx, - struct local_context *lctx, - struct ldb_dn *leaf_dn) +static int local_db_check_containers(TALLOC_CTX *mem_ctx, + struct local_context *lctx, + struct ldb_dn *leaf_dn) { static const char *attrs[] = { NULL}; struct ldb_result *res = NULL; @@ -316,10 +316,10 @@ int local_db_check_containers(TALLOC_CTX *mem_ctx, return EOK; } -int local_db_put_simple(TALLOC_CTX *mem_ctx, - struct local_context *lctx, - const char *req_path, - const char *secret) +static int local_db_put_simple(TALLOC_CTX *mem_ctx, + struct local_context *lctx, + const char *req_path, + const char *secret) { struct ldb_message *msg; const char *enctype = "masterkey"; @@ -368,9 +368,9 @@ int local_db_put_simple(TALLOC_CTX *mem_ctx, return ret; } -int local_db_delete(TALLOC_CTX *mem_ctx, - struct local_context *lctx, - const char *req_path) +static int local_db_delete(TALLOC_CTX *mem_ctx, + struct local_context *lctx, + const char *req_path) { TALLOC_CTX *tmp_ctx; struct ldb_dn *dn; @@ -411,9 +411,9 @@ int local_db_delete(TALLOC_CTX *mem_ctx, return ret; } -int local_db_create(TALLOC_CTX *mem_ctx, - struct local_context *lctx, - const char *req_path) +static int local_db_create(TALLOC_CTX *mem_ctx, + struct local_context *lctx, + const char *req_path) { struct ldb_message *msg; int ret; @@ -451,9 +451,9 @@ int local_db_create(TALLOC_CTX *mem_ctx, return ret; } -int local_secrets_map_path(TALLOC_CTX *mem_ctx, - struct sec_req_ctx *secreq, - char **local_db_path) +static int local_secrets_map_path(TALLOC_CTX *mem_ctx, + struct sec_req_ctx *secreq, + char **local_db_path) { int ret; @@ -501,10 +501,10 @@ struct local_secret_state { struct sec_req_ctx *secreq; }; -struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - void *provider_ctx, - struct sec_req_ctx *secreq) +static struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + void *provider_ctx, + struct sec_req_ctx *secreq) { struct tevent_req *req; struct local_secret_state *state; @@ -633,7 +633,7 @@ struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx, return tevent_req_post(req, state->ev); } -int generate_master_key(const char *filename, size_t size) +static int generate_master_key(const char *filename, size_t size) { uint8_t buf[size]; ssize_t rsize; From 75bab87d402c63d4ae6edd3b1554792179da6d41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fiden...@redhat.com> Date: Mon, 26 Sep 2016 01:15:56 +0200 Subject: [PATCH 6/7] SECRETS: Use a tmp_context on local_db_check_containers() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise the struct ldb_dn will be hanging on the mem_ctx till it gets freed. Signed-off-by: Fabiano Fidêncio <fiden...@redhat.com> --- src/responder/secrets/local.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c index 0ce0526..484e406 100644 --- a/src/responder/secrets/local.c +++ b/src/responder/secrets/local.c @@ -286,14 +286,21 @@ static int local_db_check_containers(TALLOC_CTX *mem_ctx, struct local_context *lctx, struct ldb_dn *leaf_dn) { + TALLOC_CTX *tmp_ctx; static const char *attrs[] = { NULL}; struct ldb_result *res = NULL; struct ldb_dn *dn; int num; int ret; - dn = ldb_dn_copy(mem_ctx, leaf_dn); - if (!dn) return ENOMEM; + tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) return ENOMEM; + + dn = ldb_dn_copy(tmp_ctx, leaf_dn); + if (!dn) { + ret = ENOMEM; + goto done; + } /* We need to exclude the leaf as that will be the new child entry, * We also do not care for the synthetic containers that constitute the @@ -306,14 +313,23 @@ static int local_db_check_containers(TALLOC_CTX *mem_ctx, if (!ldb_dn_remove_child_components(dn, 1)) return EFAULT; /* and check the parent container exists */ - ret = ldb_search(lctx->ldb, mem_ctx, &res, dn, LDB_SCOPE_BASE, + ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, attrs, LOCAL_CONTAINER_FILTER); - if (ret != LDB_SUCCESS) return ENOENT; - if (res->count != 1) return ENOENT; - talloc_free(res); + if (ret != LDB_SUCCESS) { + ret = ENOENT; + goto done; + } + if (res->count != 1) { + ret = ENOENT; + goto done; + } } - return EOK; + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; } static int local_db_put_simple(TALLOC_CTX *mem_ctx, From 3f14148cd000205385b39527f307e4e63999aa6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fiden...@redhat.com> Date: Fri, 23 Sep 2016 15:23:23 +0200 Subject: [PATCH 7/7] SECRETS: Add a configurable depth limit for nested containers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves: https://fedorahosted.org/sssd/ticket/3168 Signed-off-by: Fabiano Fidêncio <fiden...@redhat.com> --- src/confdb/confdb.h | 1 + src/config/cfg_rules.ini | 1 + src/man/sssd-secrets.5.xml | 12 ++++++++++++ src/responder/secrets/local.c | 26 ++++++++++++++++++++++++++ src/responder/secrets/providers.c | 1 + src/responder/secrets/secsrv.c | 13 +++++++++++++ src/responder/secrets/secsrv.h | 1 + src/tests/intg/test_secrets.py | 12 ++++++++++++ src/util/util_errors.c | 1 + src/util/util_errors.h | 1 + 10 files changed, 69 insertions(+) diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index 36a2f21..88f3960 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -223,6 +223,7 @@ /* Secrets Service */ #define CONFDB_SEC_CONF_ENTRY "config/secrets" +#define CONFDB_SEC_MAX_CONTAINERS_NESTED_LEVEL "secrets_max_containers_nested_level" struct confdb_ctx; diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini index 1ee98e5..443ba9e 100644 --- a/src/config/cfg_rules.ini +++ b/src/config/cfg_rules.ini @@ -228,6 +228,7 @@ option = description # Secrets service option = provider +option = secrets_max_containers_nested_level # Secrets service - proxy option = proxy_url option = auth_type diff --git a/src/man/sssd-secrets.5.xml b/src/man/sssd-secrets.5.xml index 71a79f5..69ab9a4 100644 --- a/src/man/sssd-secrets.5.xml +++ b/src/man/sssd-secrets.5.xml @@ -144,6 +144,18 @@ systemctl enable sssd-secrets.service </para> </listitem> </varlistentry> + <varlistentry> + <term>secrets_max_containers_nested_level (integer)</term> + <listitem> + <para> + This option specifies the maximum allowed number of nested + containers. + </para> + <para> + Default: 4 + </para> + </listitem> + </varlistentry> </variablelist> <para> The following options are only applicable for configurations that diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c index 484e406..1c9ed11 100644 --- a/src/responder/secrets/local.c +++ b/src/responder/secrets/local.c @@ -29,6 +29,7 @@ struct local_context { struct ldb_context *ldb; struct sec_data master_key; + int max_containers_nested_level; }; static int local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx, @@ -332,6 +333,26 @@ static int local_db_check_containers(TALLOC_CTX *mem_ctx, return ret; } +static int local_db_check_containers_nested_level(struct local_context *lctx, + struct ldb_dn *leaf_dn) +{ + int nested_level; + + /* We need do not care for the synthetic containers that constitute the + * base path (cn=<uidnumber>,cn=user,cn=secrets). */ + nested_level = ldb_dn_get_comp_num(leaf_dn) - 3; + if (nested_level > lctx->max_containers_nested_level) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot create a nested container of depth %d as the maximum" + "allowed number of nested containers is %d.\n", + nested_level, lctx->max_containers_nested_level); + + return ERR_SEC_INVALID_NESTED_CONTAINER_LEVEL; + } + + return EOK; +} + static int local_db_put_simple(TALLOC_CTX *mem_ctx, struct local_context *lctx, const char *req_path, @@ -447,6 +468,9 @@ static int local_db_create(TALLOC_CTX *mem_ctx, ret = local_db_check_containers(msg, lctx, msg->dn); if (ret != EOK) goto done; + ret = local_db_check_containers_nested_level(lctx, msg->dn); + if (ret != EOK) goto done; + ret = ldb_msg_add_string(msg, "type", "container"); if (ret != EOK) goto done; @@ -708,6 +732,8 @@ int local_secrets_provider_handle(struct sec_ctx *sctx, return EIO; } + lctx->max_containers_nested_level = sctx->max_containers_nested_level; + lctx->master_key.data = talloc_size(lctx, MKEY_SIZE); if (!lctx->master_key.data) return ENOMEM; lctx->master_key.length = MKEY_SIZE; diff --git a/src/responder/secrets/providers.c b/src/responder/secrets/providers.c index 4c60198..fc509f2 100644 --- a/src/responder/secrets/providers.c +++ b/src/responder/secrets/providers.c @@ -306,6 +306,7 @@ enum sec_http_status_codes sec_errno_to_http_status(errno_t err) case EISDIR: return STATUS_405; case EMEDIUMTYPE: + case ERR_SEC_INVALID_NESTED_CONTAINER_LEVEL: return STATUS_406; case EEXIST: return STATUS_409; diff --git a/src/responder/secrets/secsrv.c b/src/responder/secrets/secsrv.c index eb194a1..588749c 100644 --- a/src/responder/secrets/secsrv.c +++ b/src/responder/secrets/secsrv.c @@ -29,6 +29,7 @@ #include "resolv/async_resolv.h" #define DEFAULT_SEC_FD_LIMIT 2048 +#define DEFAULT_SEC_MAX_CONTAINERS_NESTED_LEVEL 4 static int sec_get_config(struct sec_ctx *sctx) { @@ -45,6 +46,18 @@ 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_MAX_CONTAINERS_NESTED_LEVEL, + DEFAULT_SEC_MAX_CONTAINERS_NESTED_LEVEL, + &sctx->max_containers_nested_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_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 ace30f8..ecca12f 100644 --- a/src/responder/secrets/secsrv.h +++ b/src/responder/secrets/secsrv.h @@ -38,6 +38,7 @@ struct sec_ctx { struct resolv_ctx *resctx; struct resp_ctx *rctx; int fd_limit; + int max_containers_nested_level; struct provider_handle **providers; }; diff --git a/src/tests/intg/test_secrets.py b/src/tests/intg/test_secrets.py index e394d12..221ec0a 100644 --- a/src/tests/intg/test_secrets.py +++ b/src/tests/intg/test_secrets.py @@ -160,3 +160,15 @@ def test_containers(setup_for_secrets, secrets_cli): # Try removing the secret first, then the container cli.del_secret("mycontainer/foo") cli.del_secret("mycontainer/") + + # Don't allow creating a container after reaching the max nested level + DEFAULT_CONTAINERS_NESTED_LEVEL = 4 + container = "mycontainer" + for x in xrange(DEFAULT_CONTAINERS_NESTED_LEVEL): + container += "%s/" % str(x) + cli.create_container(container) + + container += "%s/" % str(DEFAULT_CONTAINERS_NESTED_LEVEL) + with pytest.raises(HTTPError) as err406: + cli.create_container(container) + assert str(err406.value).startswith("406") diff --git a/src/util/util_errors.c b/src/util/util_errors.c index 620be3c..66a033a 100644 --- a/src/util/util_errors.c +++ b/src/util/util_errors.c @@ -98,6 +98,7 @@ struct err_string error_to_str[] = { { "Dereference threshold reached" }, /* ERR_DEREF_THRESHOLD */ { "The user is not handled by SSSD" }, /* ERR_NON_SSSD_USER */ { "The internal name format cannot be parsed" }, /* ERR_WRONG_NAME_FORMAT */ + { "The maximum level of nested containers has been reached" }, /* ERR_SEC_INVALID_NESTED_CONTAINER_LEVEL */ { "ERR_LAST" } /* ERR_LAST */ }; diff --git a/src/util/util_errors.h b/src/util/util_errors.h index 1f00ba3..ae9ca07 100644 --- a/src/util/util_errors.h +++ b/src/util/util_errors.h @@ -120,6 +120,7 @@ enum sssd_errors { ERR_DEREF_THRESHOLD, ERR_NON_SSSD_USER, ERR_WRONG_NAME_FORMAT, + ERR_SEC_INVALID_NESTED_CONTAINER_LEVEL, ERR_LAST /* ALWAYS LAST */ };
_______________________________________________ sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org