mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-01 17:35:17 +00:00
Secret manipulation internal API
* include/libvirt/virterror.h, src/virterror.c: Add VIR_WAR_NO_SECRET * src/libvirt_private.syms, src/datatypes.h, src/datatypes.c: Type virSecret struct definition and helper APIs * src/driver.h: Sub-driver API definitions for secrets * src/libvirt.c: Define new sub-driver for secrets
This commit is contained in:
parent
6acc17af8c
commit
eb42e0ab5c
@ -166,6 +166,7 @@ typedef enum {
|
||||
VIR_ERR_NO_INTERFACE, /* interface driver not running */
|
||||
VIR_ERR_INVALID_INTERFACE, /* invalid interface object */
|
||||
VIR_ERR_MULTIPLE_INTERFACES, /* more than one matching interface found */
|
||||
VIR_WAR_NO_SECRET, /* failed to start secret storage */
|
||||
} virErrorNumber;
|
||||
|
||||
/**
|
||||
|
155
src/datatypes.c
155
src/datatypes.c
@ -108,6 +108,23 @@ virStorageVolFreeName(virStorageVolPtr vol, const char *name ATTRIBUTE_UNUSED)
|
||||
return (virUnrefStorageVol(vol));
|
||||
}
|
||||
|
||||
/**
|
||||
* virSecretFreeName:
|
||||
* @secret_: a secret object
|
||||
*
|
||||
* Destroy the secret object, this is just used by the secret hash callback.
|
||||
*
|
||||
* Returns 0 in case of success and -1 in case of failure.
|
||||
*/
|
||||
static void
|
||||
virSecretFreeName(void *secret_, const char *name ATTRIBUTE_UNUSED)
|
||||
{
|
||||
virSecretPtr secret;
|
||||
|
||||
secret = secret_;
|
||||
virUnrefSecret(secret);
|
||||
}
|
||||
|
||||
/**
|
||||
* virGetConnect:
|
||||
*
|
||||
@ -152,6 +169,9 @@ virGetConnect(void) {
|
||||
ret->nodeDevices = virHashCreate(256);
|
||||
if (ret->nodeDevices == NULL)
|
||||
goto failed;
|
||||
ret->secrets = virHashCreate(20);
|
||||
if (ret->secrets == NULL)
|
||||
goto failed;
|
||||
|
||||
ret->refs = 1;
|
||||
return(ret);
|
||||
@ -170,6 +190,8 @@ failed:
|
||||
virHashFree(ret->storageVols, (virHashDeallocator) virStorageVolFreeName);
|
||||
if (ret->nodeDevices != NULL)
|
||||
virHashFree(ret->nodeDevices, (virHashDeallocator) virNodeDeviceFree);
|
||||
if (ret->secrets != NULL)
|
||||
virHashFree(ret->secrets, virSecretFreeName);
|
||||
|
||||
virMutexDestroy(&ret->lock);
|
||||
VIR_FREE(ret);
|
||||
@ -201,6 +223,8 @@ virReleaseConnect(virConnectPtr conn) {
|
||||
virHashFree(conn->storageVols, (virHashDeallocator) virStorageVolFreeName);
|
||||
if (conn->nodeDevices != NULL)
|
||||
virHashFree(conn->nodeDevices, (virHashDeallocator) virNodeDeviceFree);
|
||||
if (conn->secrets != NULL)
|
||||
virHashFree(conn->secrets, virSecretFreeName);
|
||||
|
||||
virResetError(&conn->err);
|
||||
|
||||
@ -246,6 +270,8 @@ virUnrefConnect(virConnectPtr conn) {
|
||||
conn->storageDriver->close (conn);
|
||||
if (conn->deviceMonitor)
|
||||
conn->deviceMonitor->close (conn);
|
||||
if (conn->secretDriver)
|
||||
conn->secretDriver->close (conn);
|
||||
if (conn->driver)
|
||||
conn->driver->close (conn);
|
||||
|
||||
@ -1129,3 +1155,132 @@ virUnrefNodeDevice(virNodeDevicePtr dev) {
|
||||
virMutexUnlock(&dev->conn->lock);
|
||||
return (refs);
|
||||
}
|
||||
|
||||
/**
|
||||
* virGetSecret:
|
||||
* @conn: the hypervisor connection
|
||||
* @uuid: secret UUID
|
||||
*
|
||||
* Lookup if the secret is already registered for that connection, if so return
|
||||
* a pointer to it, otherwise allocate a new structure, and register it in the
|
||||
* table. In any case a corresponding call to virFreeSecret() is needed to not
|
||||
* leak data.
|
||||
*
|
||||
* Returns a pointer to the secret, or NULL in case of failure
|
||||
*/
|
||||
virSecretPtr
|
||||
virGetSecret(virConnectPtr conn, const char *uuid)
|
||||
{
|
||||
virSecretPtr ret = NULL;
|
||||
|
||||
if (!VIR_IS_CONNECT(conn) || uuid == NULL) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
virMutexLock(&conn->lock);
|
||||
|
||||
ret = virHashLookup(conn->secrets, uuid);
|
||||
if (ret == NULL) {
|
||||
if (VIR_ALLOC(ret) < 0) {
|
||||
virMutexUnlock(&conn->lock);
|
||||
virReportOOMError(conn);
|
||||
goto error;
|
||||
}
|
||||
ret->magic = VIR_SECRET_MAGIC;
|
||||
ret->conn = conn;
|
||||
ret->uuid = strdup(uuid);
|
||||
if (ret->uuid == NULL) {
|
||||
virMutexUnlock(&conn->lock);
|
||||
virReportOOMError(conn);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (virHashAddEntry(conn->secrets, uuid, ret) < 0) {
|
||||
virMutexUnlock(&conn->lock);
|
||||
virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("failed to add secret to conn hash table"));
|
||||
goto error;
|
||||
}
|
||||
conn->refs++;
|
||||
}
|
||||
ret->refs++;
|
||||
virMutexUnlock(&conn->lock);
|
||||
return ret;
|
||||
|
||||
error:
|
||||
if (ret != NULL) {
|
||||
VIR_FREE(ret->uuid);
|
||||
VIR_FREE(ret);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* virReleaseSecret:
|
||||
* @secret: the secret to release
|
||||
*
|
||||
* Unconditionally release all memory associated with a secret. The conn.lock
|
||||
* mutex must be held prior to calling this, and will be released prior to this
|
||||
* returning. The secret obj must not be used once this method returns.
|
||||
*
|
||||
* It will also unreference the associated connection object, which may also be
|
||||
* released if its ref count hits zero.
|
||||
*/
|
||||
static void
|
||||
virReleaseSecret(virSecretPtr secret) {
|
||||
virConnectPtr conn = secret->conn;
|
||||
DEBUG("release secret %p %s", secret, secret->uuid);
|
||||
|
||||
if (virHashRemoveEntry(conn->secrets, secret->uuid, NULL) < 0) {
|
||||
virMutexUnlock(&conn->lock);
|
||||
virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("secret missing from connection hash table"));
|
||||
conn = NULL;
|
||||
}
|
||||
|
||||
secret->magic = -1;
|
||||
VIR_FREE(secret->uuid);
|
||||
VIR_FREE(secret);
|
||||
|
||||
if (conn) {
|
||||
DEBUG("unref connection %p %d", conn, conn->refs);
|
||||
conn->refs--;
|
||||
if (conn->refs == 0) {
|
||||
virReleaseConnect(conn);
|
||||
/* Already unlocked mutex */
|
||||
return;
|
||||
}
|
||||
virMutexUnlock(&conn->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* virUnrefSecret:
|
||||
* @secret: the secret to unreference
|
||||
*
|
||||
* Unreference the secret. If the use count drops to zero, the structure is
|
||||
* actually freed.
|
||||
*
|
||||
* Returns the reference count or -1 in case of failure.
|
||||
*/
|
||||
int
|
||||
virUnrefSecret(virSecretPtr secret) {
|
||||
int refs;
|
||||
|
||||
if (!VIR_IS_CONNECTED_SECRET(secret)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
virMutexLock(&secret->conn->lock);
|
||||
DEBUG("unref secret %p %s %d", secret, secret->uuid, secret->refs);
|
||||
secret->refs--;
|
||||
refs = secret->refs;
|
||||
if (refs == 0) {
|
||||
virReleaseSecret(secret);
|
||||
/* Already unlocked mutex */
|
||||
return 0;
|
||||
}
|
||||
|
||||
virMutexUnlock(&secret->conn->lock);
|
||||
return refs;
|
||||
}
|
||||
|
@ -98,6 +98,16 @@
|
||||
#define VIR_IS_NODE_DEVICE(obj) ((obj) && (obj)->magic==VIR_NODE_DEVICE_MAGIC)
|
||||
#define VIR_IS_CONNECTED_NODE_DEVICE(obj) (VIR_IS_NODE_DEVICE(obj) && VIR_IS_CONNECT((obj)->conn))
|
||||
|
||||
/**
|
||||
* VIR_SECRET_MAGIC:
|
||||
*
|
||||
* magic value used to protect the API when pointers to secret structures are
|
||||
* passed down by the users.
|
||||
*/
|
||||
#define VIR_SECRET_MAGIC 0x5678DEAD
|
||||
#define VIR_IS_SECRET(obj) ((obj) && (obj)->magic==VIR_SECRET_MAGIC)
|
||||
#define VIR_IS_CONNECTED_SECRET(obj) (VIR_IS_SECRET(obj) && VIR_IS_CONNECT((obj)->conn))
|
||||
|
||||
|
||||
/**
|
||||
* _virConnect:
|
||||
@ -119,6 +129,7 @@ struct _virConnect {
|
||||
virInterfaceDriverPtr interfaceDriver;
|
||||
virStorageDriverPtr storageDriver;
|
||||
virDeviceMonitorPtr deviceMonitor;
|
||||
virSecretDriverPtr secretDriver;
|
||||
|
||||
/* Private data pointer which can be used by driver and
|
||||
* network driver as they wish.
|
||||
@ -149,6 +160,7 @@ struct _virConnect {
|
||||
virHashTablePtr storagePools;/* hash table for known storage pools */
|
||||
virHashTablePtr storageVols;/* hash table for known storage vols */
|
||||
virHashTablePtr nodeDevices; /* hash table for known node devices */
|
||||
virHashTablePtr secrets; /* hash taboe for known secrets */
|
||||
int refs; /* reference count */
|
||||
};
|
||||
|
||||
@ -233,6 +245,18 @@ struct _virNodeDevice {
|
||||
char *parent; /* parent device name */
|
||||
};
|
||||
|
||||
/**
|
||||
* _virSecret:
|
||||
*
|
||||
* Internal structure associated with a secret
|
||||
*/
|
||||
struct _virSecret {
|
||||
unsigned int magic; /* specific value to check */
|
||||
int refs; /* reference count */
|
||||
virConnectPtr conn; /* pointer back to the connection */
|
||||
char *uuid; /* ID of the secret */
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
@ -270,4 +294,8 @@ virNodeDevicePtr virGetNodeDevice(virConnectPtr conn,
|
||||
const char *name);
|
||||
int virUnrefNodeDevice(virNodeDevicePtr dev);
|
||||
|
||||
virSecretPtr virGetSecret(virConnectPtr conn,
|
||||
const char *uuid);
|
||||
int virUnrefSecret(virSecretPtr secret);
|
||||
|
||||
#endif
|
||||
|
60
src/driver.h
60
src/driver.h
@ -6,6 +6,9 @@
|
||||
#ifndef __VIR_DRIVER_H__
|
||||
#define __VIR_DRIVER_H__
|
||||
|
||||
#include "config.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <libxml/uri.h>
|
||||
|
||||
#include "internal.h"
|
||||
@ -799,6 +802,62 @@ struct _virDeviceMonitor {
|
||||
virDrvNodeDeviceDestroy deviceDestroy;
|
||||
};
|
||||
|
||||
typedef virSecretPtr
|
||||
(*virDrvSecretLookupByUUIDString) (virConnectPtr conn,
|
||||
const char *uuid);
|
||||
typedef virSecretPtr
|
||||
(*virDrvSecretDefineXML) (virConnectPtr conn,
|
||||
const char *xml,
|
||||
unsigned int flags);
|
||||
typedef char *
|
||||
(*virDrvSecretGetXMLDesc) (virSecretPtr secret,
|
||||
unsigned int flags);
|
||||
typedef int
|
||||
(*virDrvSecretSetValue) (virSecretPtr secret,
|
||||
const unsigned char *value,
|
||||
size_t value_size,
|
||||
unsigned int flags);
|
||||
typedef unsigned char *
|
||||
(*virDrvSecretGetValue) (virSecretPtr secret,
|
||||
size_t *value_size,
|
||||
unsigned int flags);
|
||||
typedef int
|
||||
(*virDrvSecretUndefine) (virSecretPtr secret);
|
||||
typedef int
|
||||
(*virDrvSecretNumOfSecrets) (virConnectPtr conn);
|
||||
typedef int
|
||||
(*virDrvSecretListSecrets) (virConnectPtr conn,
|
||||
char **uuids,
|
||||
int maxuuids);
|
||||
|
||||
typedef struct _virSecretDriver virSecretDriver;
|
||||
typedef virSecretDriver *virSecretDriverPtr;
|
||||
|
||||
/**
|
||||
* _virSecretDriver:
|
||||
*
|
||||
* Structure associated to a driver for storing secrets, defining the various
|
||||
* entry points for it.
|
||||
*
|
||||
* All drivers must support the following fields/methods:
|
||||
* - open
|
||||
* - close
|
||||
*/
|
||||
struct _virSecretDriver {
|
||||
const char *name;
|
||||
virDrvOpen open;
|
||||
virDrvClose close;
|
||||
|
||||
virDrvSecretNumOfSecrets numOfSecrets;
|
||||
virDrvSecretListSecrets listSecrets;
|
||||
virDrvSecretLookupByUUIDString lookupByUUIDString;
|
||||
virDrvSecretDefineXML defineXML;
|
||||
virDrvSecretGetXMLDesc getXMLDesc;
|
||||
virDrvSecretSetValue setValue;
|
||||
virDrvSecretGetValue getValue;
|
||||
virDrvSecretUndefine undefine;
|
||||
};
|
||||
|
||||
/*
|
||||
* Registration
|
||||
* TODO: also need ways to (des)activate a given driver
|
||||
@ -809,6 +868,7 @@ int virRegisterNetworkDriver(virNetworkDriverPtr);
|
||||
int virRegisterInterfaceDriver(virInterfaceDriverPtr);
|
||||
int virRegisterStorageDriver(virStorageDriverPtr);
|
||||
int virRegisterDeviceMonitor(virDeviceMonitorPtr);
|
||||
int virRegisterSecretDriver(virSecretDriverPtr);
|
||||
#ifdef WITH_LIBVIRTD
|
||||
int virRegisterStateDriver(virStateDriverPtr);
|
||||
#endif
|
||||
|
@ -86,6 +86,8 @@ static virStorageDriverPtr virStorageDriverTab[MAX_DRIVERS];
|
||||
static int virStorageDriverTabCount = 0;
|
||||
static virDeviceMonitorPtr virDeviceMonitorTab[MAX_DRIVERS];
|
||||
static int virDeviceMonitorTabCount = 0;
|
||||
static virSecretDriverPtr virSecretDriverTab[MAX_DRIVERS];
|
||||
static int virSecretDriverTabCount = 0;
|
||||
#ifdef WITH_LIBVIRTD
|
||||
static virStateDriverPtr virStateDriverTab[MAX_DRIVERS];
|
||||
static int virStateDriverTabCount = 0;
|
||||
@ -683,6 +685,37 @@ virRegisterDeviceMonitor(virDeviceMonitorPtr driver)
|
||||
return virDeviceMonitorTabCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* virRegisterSecretDriver:
|
||||
* @driver: pointer to a secret driver block
|
||||
*
|
||||
* Register a secret driver
|
||||
*
|
||||
* Returns the driver priority or -1 in case of error.
|
||||
*/
|
||||
int
|
||||
virRegisterSecretDriver(virSecretDriverPtr driver)
|
||||
{
|
||||
if (virInitialize() < 0)
|
||||
return -1;
|
||||
|
||||
if (driver == NULL) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (virSecretDriverTabCount >= MAX_DRIVERS) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
DEBUG ("registering %s as secret driver %d",
|
||||
driver->name, virSecretDriverTabCount);
|
||||
|
||||
virSecretDriverTab[virSecretDriverTabCount] = driver;
|
||||
return virSecretDriverTabCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* virRegisterDriver:
|
||||
* @driver: pointer to a driver block
|
||||
@ -1096,6 +1129,26 @@ do_open (const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
/* Secret manipulation driver. Optional */
|
||||
for (i = 0; i < virSecretDriverTabCount; i++) {
|
||||
res = virSecretDriverTab[i]->open (ret, auth, flags);
|
||||
DEBUG("secret driver %d %s returned %s",
|
||||
i, virSecretDriverTab[i]->name,
|
||||
res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
|
||||
(res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
|
||||
(res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
|
||||
if (res == VIR_DRV_OPEN_ERROR) {
|
||||
if (STREQ(virSecretDriverTab[i]->name, "remote")) {
|
||||
virLibConnWarning (NULL, VIR_WAR_NO_SECRET,
|
||||
"Is the daemon running ?");
|
||||
}
|
||||
break;
|
||||
} else if (res == VIR_DRV_OPEN_SUCCESS) {
|
||||
ret->secretDriver = virSecretDriverTab[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
failed:
|
||||
|
@ -52,10 +52,12 @@ virGetInterface;
|
||||
virGetNetwork;
|
||||
virGetStoragePool;
|
||||
virGetStorageVol;
|
||||
virGetSecret;
|
||||
virUnrefStorageVol;
|
||||
virGetNodeDevice;
|
||||
virUnrefDomain;
|
||||
virUnrefConnect;
|
||||
virUnrefSecret;
|
||||
|
||||
|
||||
# domain_conf.h
|
||||
|
@ -1068,6 +1068,12 @@ virErrorMsg(virErrorNumber error, const char *info)
|
||||
else
|
||||
errmsg = _("multiple matching interfaces found: %s");
|
||||
break;
|
||||
case VIR_WAR_NO_SECRET:
|
||||
if (info == NULL)
|
||||
errmsg = _("Failed to find a secret storage driver");
|
||||
else
|
||||
errmsg = _("Failed to find a secret storage driver: %s");
|
||||
break;
|
||||
}
|
||||
return (errmsg);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user