diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2017-03-20 11:49:43 +0100 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2017-03-27 09:58:48 +0200 |
commit | cac0db2f8004ae88b9263dc3888a11a2d3d3d114 (patch) | |
tree | f1f73ae5080f1d38522ac609dae4411d3679171e /src/tests | |
parent | c9db8b8b19827c3d492b8d2769aa77a37dbc12d3 (diff) | |
download | sssd-cac0db2f8004ae88b9263dc3888a11a2d3d3d114.tar.gz sssd-cac0db2f8004ae88b9263dc3888a11a2d3d3d114.tar.xz sssd-cac0db2f8004ae88b9263dc3888a11a2d3d3d114.zip |
KCM: Store ccaches in secrets
Adds a new KCM responder ccache back end that forwards all requests to
sssd-secrets.
Reviewed-by: Michal Židek <mzidek@redhat.com>
Reviewed-by: Simo Sorce <simo@redhat.com>
Diffstat (limited to 'src/tests')
-rw-r--r-- | src/tests/cmocka/test_kcm_json_marshalling.c | 234 | ||||
-rw-r--r-- | src/tests/intg/test_kcm.py | 132 |
2 files changed, 343 insertions, 23 deletions
diff --git a/src/tests/cmocka/test_kcm_json_marshalling.c b/src/tests/cmocka/test_kcm_json_marshalling.c new file mode 100644 index 000000000..8eff2f501 --- /dev/null +++ b/src/tests/cmocka/test_kcm_json_marshalling.c @@ -0,0 +1,234 @@ +/* + Copyright (C) 2017 Red Hat + + SSSD tests: Test KCM JSON marshalling + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "config.h" + +#include <stdio.h> +#include <popt.h> + +#include "util/util_creds.h" +#include "responder/kcm/kcmsrv_ccache.h" +#include "responder/kcm/kcmsrv_ccache_be.h" +#include "tests/cmocka/common_mock.h" + +#define TEST_REALM "TESTREALM" +#define TEST_PRINC_COMPONENT "PRINC_NAME" + +#define TEST_CREDS "TESTCREDS" + +const struct kcm_ccdb_ops ccdb_mem_ops; +const struct kcm_ccdb_ops ccdb_sec_ops; + +struct kcm_marshalling_test_ctx { + krb5_context kctx; + krb5_principal princ; +}; + +static int setup_kcm_marshalling(void **state) +{ + struct kcm_marshalling_test_ctx *test_ctx; + krb5_error_code kerr; + + test_ctx = talloc_zero(NULL, struct kcm_marshalling_test_ctx); + assert_non_null(test_ctx); + + kerr = krb5_init_context(&test_ctx->kctx); + assert_int_equal(kerr, 0); + + kerr = krb5_build_principal(test_ctx->kctx, + &test_ctx->princ, + sizeof(TEST_REALM)-1, TEST_REALM, + TEST_PRINC_COMPONENT, NULL); + assert_int_equal(kerr, 0); + + *state = test_ctx; + return 0; +} + +static int teardown_kcm_marshalling(void **state) +{ + struct kcm_marshalling_test_ctx *test_ctx = talloc_get_type(*state, + struct kcm_marshalling_test_ctx); + assert_non_null(test_ctx); + + krb5_free_principal(test_ctx->kctx, test_ctx->princ); + krb5_free_context(test_ctx->kctx); + talloc_free(test_ctx); + return 0; +} + +static void assert_cc_name_equal(struct kcm_ccache *cc1, + struct kcm_ccache *cc2) +{ + const char *name1, *name2; + + name1 = kcm_cc_get_name(cc1); + name2 = kcm_cc_get_name(cc2); + assert_string_equal(name1, name2); +} + +static void assert_cc_uuid_equal(struct kcm_ccache *cc1, + struct kcm_ccache *cc2) +{ + uuid_t u1, u2; + errno_t ret; + + ret = kcm_cc_get_uuid(cc1, u1); + assert_int_equal(ret, EOK); + ret = kcm_cc_get_uuid(cc2, u2); + assert_int_equal(ret, EOK); + ret = uuid_compare(u1, u2); + assert_int_equal(ret, 0); +} + +static void assert_cc_princ_equal(struct kcm_ccache *cc1, + struct kcm_ccache *cc2) +{ + krb5_principal p1; + krb5_principal p2; + char *name1; + char *name2; + krb5_error_code kerr; + + p1 = kcm_cc_get_client_principal(cc1); + p2 = kcm_cc_get_client_principal(cc1); + + kerr = krb5_unparse_name(NULL, p1, &name1); + assert_int_equal(kerr, 0); + kerr = krb5_unparse_name(NULL, p2, &name2); + assert_int_equal(kerr, 0); + + assert_string_equal(name1, name2); + krb5_free_unparsed_name(NULL, name1); + krb5_free_unparsed_name(NULL, name2); +} + +static void assert_cc_offset_equal(struct kcm_ccache *cc1, + struct kcm_ccache *cc2) +{ + int32_t off1; + int32_t off2; + + off1 = kcm_cc_get_offset(cc1); + off2 = kcm_cc_get_offset(cc2); + assert_int_equal(off1, off2); +} + +static void assert_cc_equal(struct kcm_ccache *cc1, + struct kcm_ccache *cc2) +{ + assert_cc_name_equal(cc1, cc2); + assert_cc_uuid_equal(cc1, cc2); + assert_cc_princ_equal(cc1, cc2); + assert_cc_offset_equal(cc1, cc2); +} + +static void test_kcm_ccache_marshall_unmarshall(void **state) +{ + struct kcm_marshalling_test_ctx *test_ctx = talloc_get_type(*state, + struct kcm_marshalling_test_ctx); + errno_t ret; + struct cli_creds owner; + struct kcm_ccache *cc; + struct kcm_ccache *cc2; + const char *url; + struct sss_iobuf *payload; + const char *name; + const char *key; + uint8_t *data; + + owner.ucred.uid = getuid(); + owner.ucred.gid = getuid(); + + name = talloc_asprintf(test_ctx, "%"SPRIuid, getuid()); + assert_non_null(name); + + ret = kcm_cc_new(test_ctx, + test_ctx->kctx, + &owner, + name, + test_ctx->princ, + &cc); + assert_int_equal(ret, EOK); + + ret = kcm_ccache_to_sec_input(test_ctx, + cc, + &owner, + &url, + &payload); + assert_int_equal(ret, EOK); + + key = strrchr(url, '/') + 1; + assert_non_null(key); + + data = sss_iobuf_get_data(payload); + assert_non_null(data); + + ret = sec_kv_to_ccache(test_ctx, + key, + (const char *) data, + &owner, + &cc2); + assert_int_equal(ret, EOK); + + assert_cc_equal(cc, cc2); +} + +int main(int argc, const char *argv[]) +{ + poptContext pc; + int opt; + int rv; + struct poptOption long_options[] = { + POPT_AUTOHELP + SSSD_DEBUG_OPTS + POPT_TABLEEND + }; + + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_kcm_ccache_marshall_unmarshall, + setup_kcm_marshalling, + teardown_kcm_marshalling), + }; + + /* Set debug level to invalid value so we can deside if -d 0 was used. */ + debug_level = SSSDBG_INVALID; + + pc = poptGetContext(argv[0], argc, argv, long_options, 0); + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + default: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + return 1; + } + } + poptFreeContext(pc); + + DEBUG_CLI_INIT(debug_level); + + /* Even though normally the tests should clean up after themselves + * they might not after a failed run. Remove the old db to be sure */ + tests_set_cwd(); + + rv = cmocka_run_group_tests(tests, NULL, NULL); + + return rv; +} diff --git a/src/tests/intg/test_kcm.py b/src/tests/intg/test_kcm.py index ad1e4923b..11f80a180 100644 --- a/src/tests/intg/test_kcm.py +++ b/src/tests/intg/test_kcm.py @@ -27,7 +27,8 @@ import signal import kdc import krb5utils import config -from util import unindent, run_shell +from util import unindent +from test_secrets import create_sssd_secrets_fixture class KcmTestEnv(object): def __init__(self, k5kdc, k5util): @@ -107,15 +108,8 @@ def create_sssd_kcm_fixture(sock_path, request): return kcm_pid -@pytest.fixture -def setup_for_kcm(request, kdc_instance): - """ - Just set up the local provider for tests and enable the KCM - responder - """ - kcm_path = os.path.join(config.RUNSTATEDIR, "kcm.socket") - - sssd_conf = unindent("""\ +def create_sssd_conf(kcm_path, ccache_storage): + return unindent("""\ [sssd] domains = local services = nss @@ -125,8 +119,11 @@ def setup_for_kcm(request, kdc_instance): [kcm] socket_path = {kcm_path} + ccache_storage = {ccache_storage} """).format(**locals()) + +def common_setup_for_kcm_mem(request, kdc_instance, kcm_path, sssd_conf): kcm_socket_include = unindent(""" [libdefaults] default_ccache_name = KCM: @@ -142,11 +139,35 @@ def setup_for_kcm(request, kdc_instance): return KcmTestEnv(kdc_instance, k5util) -def test_kcm_init_list_destroy(setup_for_kcm): +@pytest.fixture +def setup_for_kcm_mem(request, kdc_instance): + """ + Just set up the local provider for tests and enable the KCM + responder + """ + kcm_path = os.path.join(config.RUNSTATEDIR, "kcm.socket") + sssd_conf = create_sssd_conf(kcm_path, "memory") + return common_setup_for_kcm_mem(request, kdc_instance, kcm_path, sssd_conf) + +@pytest.fixture +def setup_secrets(request): + create_sssd_secrets_fixture(request) + +@pytest.fixture +def setup_for_kcm_sec(request, kdc_instance): + """ + Just set up the local provider for tests and enable the KCM + responder + """ + kcm_path = os.path.join(config.RUNSTATEDIR, "kcm.socket") + sssd_conf = create_sssd_conf(kcm_path, "secrets") + return common_setup_for_kcm_mem(request, kdc_instance, kcm_path, sssd_conf) + + +def kcm_init_list_destroy(testenv): """ Test that kinit, kdestroy and klist work with KCM """ - testenv = setup_for_kcm testenv.k5kdc.add_principal("kcmtest", "Secret123") ok = testenv.k5util.has_principal("kcmtest@KCMTEST") @@ -172,12 +193,22 @@ def test_kcm_init_list_destroy(setup_for_kcm): assert nprincs == 0 -def test_kcm_overwrite(setup_for_kcm): +def test_kcm_mem_init_list_destroy(setup_for_kcm_mem): + testenv = setup_for_kcm_mem + kcm_init_list_destroy(testenv) + + +def test_kcm_sec_init_list_destroy(setup_for_kcm_sec, + setup_secrets): + testenv = setup_for_kcm_sec + kcm_init_list_destroy(testenv) + + +def kcm_overwrite(testenv): """ That that reusing a ccache reinitializes the cache and doesn't add the same principal twice """ - testenv = setup_for_kcm testenv.k5kdc.add_principal("kcmtest", "Secret123") exp_ccache = {'kcmtest@KCMTEST': ['krbtgt/KCMTEST@KCMTEST']} @@ -192,12 +223,22 @@ def test_kcm_overwrite(setup_for_kcm): assert exp_ccache == testenv.k5util.list_all_princs() -def test_collection_init_list_destroy(setup_for_kcm): +def test_kcm_mem_overwrite(setup_for_kcm_mem): + testenv = setup_for_kcm_mem + kcm_overwrite(testenv) + + +def test_kcm_sec_overwrite(setup_for_kcm_sec, + setup_secrets): + testenv = setup_for_kcm_sec + kcm_overwrite(testenv) + + +def collection_init_list_destroy(testenv): """ Test that multiple principals and service tickets can be stored in a collection. """ - testenv = setup_for_kcm testenv.k5kdc.add_principal("alice", "alicepw") testenv.k5kdc.add_principal("bob", "bobpw") testenv.k5kdc.add_principal("carol", "carolpw") @@ -241,7 +282,11 @@ def test_collection_init_list_destroy(setup_for_kcm): out = testenv.k5util.kdestroy() assert out == 0 - assert testenv.k5util.default_principal() == 'bob@KCMTEST' + # If the default is removed, KCM just uses whetever is the first entry + # in the collection as the default. And sine the KCM back ends don't + # guarantee if they are FIFO or LIFO, just check for either alice or bob + assert testenv.k5util.default_principal() in \ + ['alice@KCMTEST', 'bob@KCMTEST'] cc_coll = testenv.k5util.list_all_princs() assert len(cc_coll) == 2 assert cc_coll['alice@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] @@ -255,11 +300,21 @@ def test_collection_init_list_destroy(setup_for_kcm): #assert len(cc_coll) == 0 -def test_kswitch(setup_for_kcm): +def test_kcm_mem_collection_init_list_destroy(setup_for_kcm_mem): + testenv = setup_for_kcm_mem + collection_init_list_destroy(testenv) + + +def test_kcm_sec_collection_init_list_destroy(setup_for_kcm_sec, + setup_secrets): + testenv = setup_for_kcm_sec + collection_init_list_destroy(testenv) + + +def exercise_kswitch(testenv): """ Test switching between principals """ - testenv = setup_for_kcm testenv.k5kdc.add_principal("alice", "alicepw") testenv.k5kdc.add_principal("bob", "bobpw") testenv.k5kdc.add_principal("host/somehostname") @@ -301,12 +356,22 @@ def test_kswitch(setup_for_kcm): 'host/differenthostname@KCMTEST']) -def test_subsidiaries(setup_for_kcm): +def test_kcm_mem_kswitch(setup_for_kcm_mem): + testenv = setup_for_kcm_mem + exercise_kswitch(testenv) + + +def test_kcm_sec_kswitch(setup_for_kcm_sec, + setup_secrets): + testenv = setup_for_kcm_sec + exercise_kswitch(testenv) + + +def exercise_subsidiaries(testenv): """ Test that subsidiary caches are usable and KCM: without specifying UID can be used to identify the collection """ - testenv = setup_for_kcm testenv.k5kdc.add_principal("alice", "alicepw") testenv.k5kdc.add_principal("bob", "bobpw") testenv.k5kdc.add_principal("host/somehostname") @@ -346,11 +411,21 @@ def test_subsidiaries(setup_for_kcm): 'host/differenthostname@KCMTEST']) -def test_kdestroy_nocache(setup_for_kcm): +def test_kcm_mem_subsidiaries(setup_for_kcm_mem): + testenv = setup_for_kcm_mem + exercise_subsidiaries(testenv) + + +def test_kcm_sec_subsidiaries(setup_for_kcm_sec, + setup_secrets): + testenv = setup_for_kcm_sec + exercise_subsidiaries(testenv) + + +def kdestroy_nocache(testenv): """ Destroying a non-existing ccache should not throw an error """ - testenv = setup_for_kcm testenv.k5kdc.add_principal("alice", "alicepw") out, _, _ = testenv.k5util.kinit("alice", "alicepw") assert out == 0 @@ -359,3 +434,14 @@ def test_kdestroy_nocache(setup_for_kcm): assert out == 0 out = testenv.k5util.kdestroy() assert out == 0 + + +def test_kcm_mem_kdestroy_nocache(setup_for_kcm_mem): + testenv = setup_for_kcm_mem + exercise_subsidiaries(testenv) + + +def test_kcm_sec_kdestroy_nocache(setup_for_kcm_sec, + setup_secrets): + testenv = setup_for_kcm_sec + exercise_subsidiaries(testenv) |