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]://&lt;host&gt;[: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

Reply via email to