On 2012年03月21日 01:33, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@xxxxxxxxxx> This defines the format for the auth credential config file and provides APIs to access the data. The config file contains one or more named 'credential' sets [credentials-$NAME] credname1=value1 credname2=value2 eg [credentials-test] authname=fred password=123456 [credentials-prod] authname=bar password=letmein There are then one or more 'auth' sets which match services/hosts and map to credential sets. [auth-$SERVICE-$HOSTNAME] credentials=$CREDENTIALS eg [auth-libvirt-test1.example.com] credentials=test [auth-libvirt-test2.example.com] credentials=test [auth-libvirt-demo3.example.com] credentials=test [auth-libvirt-prod1.example.com] credentials=prod * docs/auth.html.in: Document use of client auth config files * src/Makefile.am, src/libvirt_private.syms, src/util/virauthconfig.c, src/util/virauthconfig.h: Add APIs for processing auth.conf file --- docs/auth.html.in | 118 ++++++++++++++++++++++++++++++- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/libvirt_private.syms | 7 ++ src/util/virauthconfig.c | 175 +++++++++++++++++++++++++++++++++++++++++++++ src/util/virauthconfig.h | 45 ++++++++++++ tests/Makefile.am | 9 ++- tests/virauthconfigtest.c | 140 ++++++++++++++++++++++++++++++++++++ 8 files changed, 494 insertions(+), 2 deletions(-) create mode 100644 src/util/virauthconfig.c create mode 100644 src/util/virauthconfig.h create mode 100644 tests/virauthconfigtest.c diff --git a/docs/auth.html.in b/docs/auth.html.in index 2163959..ecff0fc 100644 --- a/docs/auth.html.in +++ b/docs/auth.html.in @@ -1,7 +1,7 @@ <?xml version="1.0"?> <html> <body> -<h1>Access control</h1> +<h1>Authentication& access control</h1> <p> When connecting to libvirt, some connections may require client authentication before allowing use of the APIs. The set of possible @@ -11,6 +11,122 @@ <ul id="toc"></ul> +<h2><a name="Auth_client_config">Client configuration</a></h2> + +<p> + When connecting to a remote hypervisor which requires authentication, +most libvirt applications will prompt the user for the credentials. It is +also possible to provide a client configuration file containing all the +authentication credentials, avoiding any interaction. Libvirt will look +for the authentication file using the following sequence: +</p> +<ol> +<li>The file path specified by the $LIBVIRT_AUTH_FILE environment + variable.</li> +<li>The file path specified by the "authfile=/some/file" URI + query parameter</li> +<li>The file $HOME/.libvirt/auth.conf</li> +<li>The file /etc/libvirt/auth.conf</li> +</ol> + +<p> + The auth configuration file uses the traditional<code>".ini"</code> + style syntax. There are two types of groups that can be present in + the config. First there are one or more<strong>credential</strong> + sets, which provide the actual authentication credentials. The keys + within the group may be: +</p> + +<ul> +<li><code>username</code>: the user login name to act as. This + is relevant for ESX, Xen, HyperV and SSH, but probably not + the one you want to libvirtd with SASL.</li> +<li><code>authname</code>: the name to authorize as. This is + what is commonly required for libvirtd with SASL.</li> +<li><code>password</code>: the secret password</li> +<li><code>realm</code>: the domain realm for SASL, mostly + unused</li> +</ul> + +<p> + Each set of credentials has a name, which is part of the group + entry name. Overall the syntax is +</p> + +<pre> +[credentials-$NAME] +credname1=value1 +credname2=value2</pre> + +<p> + For example, to define two sets of credentials used for production + and test machines, using libvirtd, and a further ESX server for dev: +</p> +<pre> +[credentials-test] +authname=fred +password=123456 + +[credentials-prod] +authname=bar +password=letmein + +[credentials-dev] +username=joe +password=hello</pre> + +<p> + The second set of groups provide mappings of credentials to + specific machine services. The config file group names compromise + the service type and host: +</p> + +<pre> +[auth-$SERVICE-$HOSTNAME] +credentials=$CREDENTIALS</pre> + +<p> + For example, following the previous example, here is how to + list some machines +</p> + +<pre> +[auth-libvirt-test1.example.com] +credentials=test + +[auth-libvirt-test2.example.com] +credentials=test + +[auth-libvirt-demo3.example.com] +credentials=test + +[auth-libvirt-prod1.example.com] +credentials=prod + +[auth-esx-dev1.example.com] +credentials=dev</pre> + +<p> + The following service types are known to libvirt +</p> + +<ol> +<li><code>libvirt</code> - used for connections to a libvirtd + server, which is configured with SASL auth</li> +<li><code>ssh</code> - used for connections to a Phyp server + over SSH</li> +<li><code>esx</code> - used for connections to an ESX or + VirtualCenter server</li> +<li><code>xen</code> - used for connections to a Xen Enterprise + sever using XenAPI</li> +</ol> + +<p> + Applications using libvirt are free to use this same configuration + file for storing other credentials. For example, it can be used + to storage VNC or SPICE login credentials +</p> + <h2><a name="ACL_server_config">Server configuration</a></h2> <p> The libvirt daemon allows the administrator to choose the authentication diff --git a/po/POTFILES.in b/po/POTFILES.in index 8eaa8ad..6488c4c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -124,6 +124,7 @@ src/util/storage_file.c src/util/sysinfo.c src/util/util.c src/util/virauth.c +src/util/virauthconfig.c src/util/viraudit.c src/util/virfile.c src/util/virhash.c diff --git a/src/Makefile.am b/src/Makefile.am index 3cbf9d7..a2aae9d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -81,6 +81,7 @@ UTIL_SOURCES = \ util/util.c util/util.h \ util/viraudit.c util/viraudit.h \ util/virauth.c util/virauth.h \ + util/virauthconfig.c util/virauthconfig.h \ util/virfile.c util/virfile.h \ util/virnodesuspend.c util/virnodesuspend.h \ util/virpidfile.c util/virpidfile.h \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 6f53aa8..09e2c35 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1171,6 +1171,13 @@ virAuthGetPassword; virAuthGetConfigFilePath; +# virauthconfig.h +virAuthConfigNew; +virAuthConfigNewData; +virAuthConfigLookup; +virAuthConfigFree;
Up virAuthConfigFree.
+ + # viraudit.h virAuditClose; virAuditEncode; diff --git a/src/util/virauthconfig.c b/src/util/virauthconfig.c new file mode 100644 index 0000000..ad98959 --- /dev/null +++ b/src/util/virauthconfig.c @@ -0,0 +1,175 @@ +/* + * virauthconfig.c: authentication config handling + * + * Copyright (C) 2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange<berrange@xxxxxxxxxx> + */ + +#include<config.h> + +#include "virauthconfig.h" + +#include "virkeyfile.h" +#include "memory.h" +#include "util.h" +#include "logging.h" +#include "virterror_internal.h" + + +struct _virAuthConfig { + virKeyFilePtr keyfile; + char *path; +}; + +#define VIR_FROM_THIS VIR_FROM_NONE + +#define virAuthReportError(code, ...) \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + + +virAuthConfigPtr virAuthConfigNew(const char *path) +{ + virAuthConfigPtr auth; + + if (VIR_ALLOC(auth)< 0) { + virReportOOMError(); + goto error; + } + + if (!(auth->path = strdup(path))) { + virReportOOMError(); + goto error; + } + + if (!(auth->keyfile = virKeyFileNew())) + goto error; + + if (virKeyFileLoadFile(auth->keyfile, path)< 0) + goto error; + + return auth; + +error: + virAuthConfigFree(auth); + return NULL; +} + + +virAuthConfigPtr virAuthConfigNewData(const char *path, + const char *data, + size_t len) +{ + virAuthConfigPtr auth; + + if (VIR_ALLOC(auth)< 0) { + virReportOOMError(); + goto error; + } + + if (!(auth->path = strdup(path))) { + virReportOOMError(); + goto error; + } + + if (!(auth->keyfile = virKeyFileNew())) + goto error; + + if (virKeyFileLoadData(auth->keyfile, path, data, len)< 0) + goto error; + + return auth; + +error: + virAuthConfigFree(auth); + return NULL; +} + + +void virAuthConfigFree(virAuthConfigPtr auth) +{ + if (!auth) + return; + + virKeyFileFree(auth->keyfile); + VIR_FREE(auth->path); + VIR_FREE(auth); +} + + +int virAuthConfigLookup(virAuthConfigPtr auth, + const char *service, + const char *hostname, + const char *credname, + const char **value) +{ + char *authgroup = NULL; + char *credgroup = NULL; + const char *authcred; + int ret = -1; + + *value = NULL; + + VIR_DEBUG("Lookup '%s' '%s' '%s'", service, NULLSTR(hostname), credname); + + if (!hostname) + hostname = "localhost"; + + if (virAsprintf(&authgroup, "auth-%s-%s", service, hostname)< 0) { + virReportOOMError(); + goto cleanup; + } + + if (!virKeyFileHasGroup(auth->keyfile, authgroup)) { + ret = 0; + goto cleanup; + } + + if (!(authcred = virKeyFileGetValueString(auth->keyfile, authgroup, "credentials"))) { + virAuthReportError(VIR_ERR_CONF_SYNTAX, + _("Missing item 'credentials' in group '%s' in '%s'"), + authgroup, auth->path); + goto cleanup; + } + + if (virAsprintf(&credgroup, "credentials-%s", authcred)< 0) { + virReportOOMError(); + goto cleanup; + } + + if (!virKeyFileHasGroup(auth->keyfile, credgroup)) { + virAuthReportError(VIR_ERR_CONF_SYNTAX, + _("Missing group 'credentials-%s' referenced from group '%s' in '%s'"), + authcred, authgroup, auth->path); + goto cleanup; + } + + if (!virKeyFileHasValue(auth->keyfile, credgroup, credname)) { + ret = 0; + goto cleanup; + } + + *value = virKeyFileGetValueString(auth->keyfile, credgroup, credname); + + ret = 0; + +cleanup: + VIR_FREE(authgroup); + VIR_FREE(credgroup); + return ret; +} diff --git a/src/util/virauthconfig.h b/src/util/virauthconfig.h new file mode 100644 index 0000000..cbeef85 --- /dev/null +++ b/src/util/virauthconfig.h @@ -0,0 +1,45 @@ +/* + * virauthconfig.h: authentication config handling + * + * Copyright (C) 2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange<berrange@xxxxxxxxxx> + */ + +#ifndef __VIR_AUTHCONFIG_H__ +# define __VIR_AUTHCONFIG_H__ + +# include "internal.h" + +typedef struct _virAuthConfig virAuthConfig; +typedef virAuthConfig *virAuthConfigPtr; + + +virAuthConfigPtr virAuthConfigNew(const char *path); +virAuthConfigPtr virAuthConfigNewData(const char *path, + const char *data, + size_t len); + +void virAuthConfigFree(virAuthConfigPtr auth); + +int virAuthConfigLookup(virAuthConfigPtr auth, + const char *service, + const char *hostname, + const char *credname, + const char **value); + +#endif /* __VIR_AUTHCONFIG_H__ */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 4dde3e9..8ba7e66 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -96,7 +96,8 @@ check_PROGRAMS = virshtest conftest sockettest \ commandtest commandhelper seclabeltest \ virhashtest virnetmessagetest virnetsockettest ssh \ utiltest virnettlscontexttest shunloadtest \ - virtimetest viruritest virkeyfiletest + virtimetest viruritest virkeyfiletest \ + virauthconfigtest check_LTLIBRARIES = libshunload.la @@ -221,6 +222,7 @@ TESTS = virshtest \ virtimetest \ viruritest \ virkeyfiletest \ + virauthconfigtest \ shunloadtest \ utiltest \ $(test_scripts) @@ -518,6 +520,11 @@ virkeyfiletest_SOURCES = \ virkeyfiletest_CFLAGS = -Dabs_builddir="\"$(abs_builddir)\"" $(AM_CFLAGS) virkeyfiletest_LDADD = ../src/libvirt-net-rpc.la $(LDADDS) +virauthconfigtest_SOURCES = \ + virauthconfigtest.c testutils.h testutils.c +virauthconfigtest_CFLAGS = -Dabs_builddir="\"$(abs_builddir)\"" $(AM_CFLAGS) +virauthconfigtest_LDADD = ../src/libvirt-net-rpc.la $(LDADDS) + seclabeltest_SOURCES = \ seclabeltest.c seclabeltest_LDADD = ../src/libvirt_driver_security.la $(LDADDS) diff --git a/tests/virauthconfigtest.c b/tests/virauthconfigtest.c new file mode 100644 index 0000000..b4f08fd --- /dev/null +++ b/tests/virauthconfigtest.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2011 Red Hat, Inc.
s/2011/2012/
+ * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange<berrange@xxxxxxxxxx> + */ + +#include<config.h> + +#include<stdlib.h> +#include<signal.h> + +#include "testutils.h" +#include "util.h" +#include "virterror_internal.h" +#include "memory.h" +#include "logging.h" + +#include "virauthconfig.h" + +#define VIR_FROM_THIS VIR_FROM_RPC + +struct ConfigLookupData { + virAuthConfigPtr config; + const char *hostname; + const char *service; + const char *credname; + const char *expect; +}; + +static int testAuthLookup(const void *args) +{ + int ret = -1; + const struct ConfigLookupData *data = args; + const char *actual = NULL; + int rv; + + rv = virAuthConfigLookup(data->config, + data->service, + data->hostname, + data->credname, +&actual); + + if (rv< 0) + goto cleanup; + + if (data->expect) { + if (!actual || + !STREQ(actual, data->expect)) { + VIR_WARN("Expected value '%s' for '%s' '%s' '%s', but got '%s'", + data->expect, data->hostname, + data->service, data->credname, + NULLSTR(actual)); + goto cleanup; + } + } else { + if (actual) { + VIR_WARN("Did not expect a value for '%s' '%s' '%s', but got '%s'", + data->hostname, + data->service, data->credname, + actual); + goto cleanup; + } + } + + ret = 0; +cleanup: + return ret; +} + + +static int +mymain(void) +{ + int ret = 0; + + virAuthConfigPtr config; + + signal(SIGPIPE, SIG_IGN); + +#define TEST_LOOKUP(config, hostname, service, credname, expect) \ + do { \ + const struct ConfigLookupData data = { \ + config, hostname, service, credname, expect \ + }; \ + if (virtTestRun("Test Lookup " hostname "-" service "-" credname, \ + 1, testAuthLookup,&data)< 0) \ + ret = -1; \ + } while (0) + + const char *confdata = + "[credentials-test]\n" + "username=fred\n" + "password=123456\n" + "\n" + "[credentials-prod]\n" + "username=bar\n" + "password=letmein\n" + "\n" + "[auth-libvirt-test1.example.com]\n" + "credentials=test\n" + "\n" + "[auth-libvirt-test2.example.com]\n" + "credentials=test\n" + "\n" + "[auth-libvirt-demo3.example.com]\n" + "credentials=test\n" + "\n" + "[auth-libvirt-prod1.example.com]\n" + "credentials=prod\n"; + + if (!(config = virAuthConfigNewData("auth.conf", confdata, strlen(confdata)))) + return EXIT_FAILURE; + + TEST_LOOKUP(config, "test1.example.com", "libvirt", "username", "fred"); + TEST_LOOKUP(config, "test1.example.com", "vnc", "username", NULL); + TEST_LOOKUP(config, "test1.example.com", "libvirt", "realm", NULL); + TEST_LOOKUP(config, "test66.example.com", "libvirt", "username", NULL); + TEST_LOOKUP(config, "prod1.example.com", "libvirt", "username", "bar"); + TEST_LOOKUP(config, "prod1.example.com", "libvirt", "password", "letmein"); + + virAuthConfigFree(config); + + return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + +VIRT_TEST_MAIN(mymain)
ACK with the nits fixed. -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list