提交 a4fb88b5 编写于 作者: D Daniel P. Berrange

Add helper API for finding auth file path

* src/util/virauth.c, src/util/virauth.h: Add virAuthGetConfigFilePath
* include/libvirt/virterror.h, src/util/virterror.c: Add
  VIR_FROM_AUTH error domain
Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
上级 4262e34e
<?xml version="1.0"?> <?xml version="1.0"?>
<html> <html>
<body> <body>
<h1 >Access control</h1> <h1 >Authentication &amp; access control</h1>
<p> <p>
When connecting to libvirt, some connections may require client When connecting to libvirt, some connections may require client
authentication before allowing use of the APIs. The set of possible authentication before allowing use of the APIs. The set of possible
...@@ -11,6 +11,122 @@ ...@@ -11,6 +11,122 @@
<ul id="toc"></ul> <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> <h2><a name="ACL_server_config">Server configuration</a></h2>
<p> <p>
The libvirt daemon allows the administrator to choose the authentication The libvirt daemon allows the administrator to choose the authentication
......
...@@ -86,6 +86,7 @@ typedef enum { ...@@ -86,6 +86,7 @@ typedef enum {
VIR_FROM_HYPERV = 43, /* Error from Hyper-V driver */ VIR_FROM_HYPERV = 43, /* Error from Hyper-V driver */
VIR_FROM_CAPABILITIES = 44, /* Error from capabilities */ VIR_FROM_CAPABILITIES = 44, /* Error from capabilities */
VIR_FROM_URI = 45, /* Error from URI handling */ VIR_FROM_URI = 45, /* Error from URI handling */
VIR_FROM_AUTH = 46, /* Error from auth handling */
} virErrorDomain; } virErrorDomain;
......
...@@ -125,6 +125,7 @@ src/util/sysinfo.c ...@@ -125,6 +125,7 @@ src/util/sysinfo.c
src/util/util.c src/util/util.c
src/util/viraudit.c src/util/viraudit.c
src/util/virauth.c src/util/virauth.c
src/util/virauthconfig.c
src/util/virfile.c src/util/virfile.c
src/util/virhash.c src/util/virhash.c
src/util/virkeyfile.c src/util/virkeyfile.c
......
...@@ -81,6 +81,7 @@ UTIL_SOURCES = \ ...@@ -81,6 +81,7 @@ UTIL_SOURCES = \
util/util.c util/util.h \ util/util.c util/util.h \
util/viraudit.c util/viraudit.h \ util/viraudit.c util/viraudit.h \
util/virauth.c util/virauth.h \ util/virauth.c util/virauth.h \
util/virauthconfig.c util/virauthconfig.h \
util/virfile.c util/virfile.h \ util/virfile.c util/virfile.h \
util/virnodesuspend.c util/virnodesuspend.h \ util/virnodesuspend.c util/virnodesuspend.h \
util/virpidfile.c util/virpidfile.h \ util/virpidfile.c util/virpidfile.h \
......
...@@ -1161,8 +1161,16 @@ virUUIDParse; ...@@ -1161,8 +1161,16 @@ virUUIDParse;
# virauth.h # virauth.h
virAuthGetUsername; virAuthGetConfigFilePath;
virAuthGetPassword; virAuthGetPassword;
virAuthGetUsername;
# virauthconfig.h
virAuthConfigFree;
virAuthConfigLookup;
virAuthConfigNew;
virAuthConfigNewData;
# viraudit.h # viraudit.h
......
...@@ -21,9 +21,83 @@ ...@@ -21,9 +21,83 @@
#include <config.h> #include <config.h>
#include <stdlib.h>
#include "virauth.h" #include "virauth.h"
#include "util.h" #include "util.h"
#include "memory.h" #include "memory.h"
#include "logging.h"
#include "datatypes.h"
#include "virterror_internal.h"
#include "configmake.h"
#define VIR_FROM_THIS VIR_FROM_AUTH
int virAuthGetConfigFilePath(virConnectPtr conn,
char **path)
{
int ret = -1;
size_t i;
const char *authenv = getenv("LIBVIRT_AUTH_FILE");
char *userdir = NULL;
*path = NULL;
VIR_DEBUG("Determining auth config file path");
if (authenv) {
VIR_DEBUG("Using path from env '%s'", authenv);
if (!(*path = strdup(authenv)))
goto no_memory;
return 0;
}
for (i = 0 ; i < conn->uri->paramsCount ; i++) {
if (STREQ_NULLABLE(conn->uri->params[i].name, "authfile") &&
conn->uri->params[i].value) {
VIR_DEBUG("Using path from URI '%s'",
conn->uri->params[i].value);
if (!(*path = strdup(conn->uri->params[i].value)))
goto no_memory;
return 0;
}
}
if (!(userdir = virGetUserDirectory(geteuid())))
goto cleanup;
if (virAsprintf(path, "%s/.libvirt/auth.conf", userdir) < 0)
goto no_memory;
VIR_DEBUG("Checking for readability of '%s'", *path);
if (access(*path, R_OK) == 0)
goto done;
VIR_FREE(*path);
if (!(*path = strdup(SYSCONFDIR "/libvirt/auth.conf")))
goto no_memory;
VIR_DEBUG("Checking for readability of '%s'", *path);
if (access(*path, R_OK) == 0)
goto done;
VIR_FREE(*path);
done:
ret = 0;
VIR_DEBUG("Using auth file '%s'", NULLSTR(*path));
cleanup:
VIR_FREE(userdir);
return ret;
no_memory:
virReportOOMError();
goto cleanup;
}
char * char *
......
...@@ -24,6 +24,9 @@ ...@@ -24,6 +24,9 @@
# include "internal.h" # include "internal.h"
int virAuthGetConfigFilePath(virConnectPtr conn,
char **path);
char *virAuthGetUsername(virConnectAuthPtr auth, const char *defaultUsername, char *virAuthGetUsername(virConnectAuthPtr auth, const char *defaultUsername,
const char *hostname); const char *hostname);
char *virAuthGetPassword(virConnectAuthPtr auth, const char *username, char *virAuthGetPassword(virConnectAuthPtr auth, const char *username,
......
/*
* 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@redhat.com>
*/
#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;
}
/*
* 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@redhat.com>
*/
#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__ */
...@@ -181,6 +181,9 @@ static const char *virErrorDomainName(virErrorDomain domain) { ...@@ -181,6 +181,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
case VIR_FROM_URI: case VIR_FROM_URI:
dom = "URI "; dom = "URI ";
break; break;
case VIR_FROM_AUTH:
dom = "Auth ";
break;
} }
return(dom); return(dom);
} }
......
...@@ -96,7 +96,8 @@ check_PROGRAMS = virshtest conftest sockettest \ ...@@ -96,7 +96,8 @@ check_PROGRAMS = virshtest conftest sockettest \
commandtest commandhelper seclabeltest \ commandtest commandhelper seclabeltest \
virhashtest virnetmessagetest virnetsockettest ssh \ virhashtest virnetmessagetest virnetsockettest ssh \
utiltest virnettlscontexttest shunloadtest \ utiltest virnettlscontexttest shunloadtest \
virtimetest viruritest virkeyfiletest virtimetest viruritest virkeyfiletest \
virauthconfigtest
check_LTLIBRARIES = libshunload.la check_LTLIBRARIES = libshunload.la
...@@ -221,6 +222,7 @@ TESTS = virshtest \ ...@@ -221,6 +222,7 @@ TESTS = virshtest \
virtimetest \ virtimetest \
viruritest \ viruritest \
virkeyfiletest \ virkeyfiletest \
virauthconfigtest \
shunloadtest \ shunloadtest \
utiltest \ utiltest \
$(test_scripts) $(test_scripts)
...@@ -518,6 +520,11 @@ virkeyfiletest_SOURCES = \ ...@@ -518,6 +520,11 @@ virkeyfiletest_SOURCES = \
virkeyfiletest_CFLAGS = -Dabs_builddir="\"$(abs_builddir)\"" $(AM_CFLAGS) virkeyfiletest_CFLAGS = -Dabs_builddir="\"$(abs_builddir)\"" $(AM_CFLAGS)
virkeyfiletest_LDADD = ../src/libvirt-net-rpc.la $(LDADDS) 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_SOURCES = \
seclabeltest.c seclabeltest.c
seclabeltest_LDADD = ../src/libvirt_driver_security.la $(LDADDS) seclabeltest_LDADD = ../src/libvirt_driver_security.la $(LDADDS)
......
/*
* 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@redhat.com>
*/
#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)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册