ERL_NIF_TERM vert_virSecretLookupByUsage(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { VERT_RESOURCE *vp = NULL; int usageType = 0; ErlNifBinary usageID = {0}; VERT_RESOURCE *sp = NULL; VERT_GET_RESOURCE(0, vp, VERT_RES_CONNECT); VERT_GET_INT(1, usageType); VERT_GET_IOLIST(2, usageID); VERT_BIN_APPEND_NULL(usageID); VERT_RES_ALLOC(sp, VERT_RES_SECRET, vp->res); sp->res = virSecretLookupByUsage(vp->res, usageType, (char *)usageID.data); if (sp->res == NULL) { enif_release_resource(vp); return verterr(env); } return vert_make_resource(env, sp, atom_secret); }
/** * Update info about a volume's capacity/allocation */ static int virStorageBackendFileSystemVolRefresh(virConnectPtr conn, virStoragePoolObjPtr pool ATTRIBUTE_UNUSED, virStorageVolDefPtr vol) { int ret; /* Refresh allocation / permissions info in case its changed */ ret = virStorageBackendUpdateVolInfo(vol, 0); if (ret < 0) return ret; /* Load any secrets if posible */ if (vol->target.encryption && vol->target.encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_QCOW && vol->target.encryption->nsecrets == 0) { virSecretPtr sec; virStorageEncryptionSecretPtr encsec = NULL; sec = virSecretLookupByUsage(conn, VIR_SECRET_USAGE_TYPE_VOLUME, vol->target.path); if (sec) { if (VIR_ALLOC_N(vol->target.encryption->secrets, 1) < 0 || VIR_ALLOC(encsec) < 0) { VIR_FREE(vol->target.encryption->secrets); virReportOOMError(); virSecretFree(sec); return -1; } vol->target.encryption->nsecrets = 1; vol->target.encryption->secrets[0] = encsec; encsec->type = VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE; virSecretGetUUID(sec, encsec->uuid); virSecretFree(sec); } } return 0; }
static int virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr *ptr, virConnectPtr conn, virStoragePoolObjPtr pool) { int ret = -1; unsigned char *secret_value = NULL; size_t secret_value_size; char *rados_key = NULL; virBuffer mon_host = VIR_BUFFER_INITIALIZER; virSecretPtr secret = NULL; char secretUuid[VIR_UUID_STRING_BUFLEN]; int i; char *mon_buff = NULL; VIR_DEBUG("Found Cephx username: %s", pool->def->source.auth.cephx.username); if (pool->def->source.auth.cephx.username != NULL) { VIR_DEBUG("Using cephx authorization"); if (rados_create(&ptr->cluster, pool->def->source.auth.cephx.username) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("failed to initialize RADOS")); goto cleanup; } if (pool->def->source.auth.cephx.secret.uuidUsable) { virUUIDFormat(pool->def->source.auth.cephx.secret.uuid, secretUuid); VIR_DEBUG("Looking up secret by UUID: %s", secretUuid); secret = virSecretLookupByUUIDString(conn, secretUuid); } else if (pool->def->source.auth.cephx.secret.usage != NULL) { VIR_DEBUG("Looking up secret by usage: %s", pool->def->source.auth.cephx.secret.usage); secret = virSecretLookupByUsage(conn, VIR_SECRET_USAGE_TYPE_CEPH, pool->def->source.auth.cephx.secret.usage); } if (secret == NULL) { virReportError(VIR_ERR_NO_SECRET, "%s", _("failed to find the secret")); goto cleanup; } secret_value = virSecretGetValue(secret, &secret_value_size, 0); base64_encode_alloc((char *)secret_value, secret_value_size, &rados_key); memset(secret_value, 0, secret_value_size); if (rados_key == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("failed to decode the RADOS key")); goto cleanup; } VIR_DEBUG("Found cephx key: %s", rados_key); if (rados_conf_set(ptr->cluster, "key", rados_key) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to set RADOS option: %s"), "rados_key"); goto cleanup; } memset(rados_key, 0, strlen(rados_key)); if (rados_conf_set(ptr->cluster, "auth_supported", "cephx") < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to set RADOS option: %s"), "auth_supported"); goto cleanup; } } else { VIR_DEBUG("Not using cephx authorization"); if (rados_create(&ptr->cluster, NULL) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("failed to create the RADOS cluster")); goto cleanup; } if (rados_conf_set(ptr->cluster, "auth_supported", "none") < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to set RADOS option: %s"), "auth_supported"); goto cleanup; } } VIR_DEBUG("Found %zu RADOS cluster monitors in the pool configuration", pool->def->source.nhost); for (i = 0; i < pool->def->source.nhost; i++) { if (pool->def->source.hosts[i].name != NULL && !pool->def->source.hosts[i].port) { virBufferAsprintf(&mon_host, "%s:6789,", pool->def->source.hosts[i].name); } else if (pool->def->source.hosts[i].name != NULL && pool->def->source.hosts[i].port) { virBufferAsprintf(&mon_host, "%s:%d,", pool->def->source.hosts[i].name, pool->def->source.hosts[i].port); } else { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("received malformed monitor, check the XML definition")); } } if (virBufferError(&mon_host)) { virReportOOMError(); goto cleanup; } mon_buff = virBufferContentAndReset(&mon_host); VIR_DEBUG("RADOS mon_host has been set to: %s", mon_buff); if (rados_conf_set(ptr->cluster, "mon_host", mon_buff) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to set RADOS option: %s"), "mon_host"); goto cleanup; } ptr->starttime = time(0); if (rados_connect(ptr->cluster) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to connect to the RADOS monitor on: %s"), mon_buff); goto cleanup; } ret = 0; cleanup: VIR_FREE(secret_value); VIR_FREE(rados_key); virSecretFree(secret); virBufferFreeAndReset(&mon_host); VIR_FREE(mon_buff); return ret; }
static int virStorageBackendISCSISetAuth(const char *portal, virConnectPtr conn, virStoragePoolDefPtr def) { virSecretPtr secret = NULL; unsigned char *secret_value = NULL; virStoragePoolAuthChap chap; int ret = -1; if (def->source.authType == VIR_STORAGE_POOL_AUTH_NONE) return 0; if (def->source.authType != VIR_STORAGE_POOL_AUTH_CHAP) { virReportError(VIR_ERR_XML_ERROR, "%s", _("iscsi pool only supports 'chap' auth type")); return -1; } if (!conn) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("iscsi 'chap' authentication not supported " "for autostarted pools")); return -1; } chap = def->source.auth.chap; if (chap.secret.uuidUsable) secret = virSecretLookupByUUID(conn, chap.secret.uuid); else secret = virSecretLookupByUsage(conn, VIR_SECRET_USAGE_TYPE_ISCSI, chap.secret.usage); if (secret) { size_t secret_size; secret_value = conn->secretDriver->secretGetValue(secret, &secret_size, 0, VIR_SECRET_GET_VALUE_INTERNAL_CALL); if (!secret_value) { virReportError(VIR_ERR_INTERNAL_ERROR, _("could not get the value of the secret " "for username %s"), chap.username); goto cleanup; } } else { virReportError(VIR_ERR_INTERNAL_ERROR, _("username '%s' specified but secret not found"), chap.username); goto cleanup; } if (virStorageBackendISCSINodeUpdate(portal, def->source.devices[0].path, "node.session.auth.authmethod", "CHAP") < 0 || virStorageBackendISCSINodeUpdate(portal, def->source.devices[0].path, "node.session.auth.username", chap.username) < 0 || virStorageBackendISCSINodeUpdate(portal, def->source.devices[0].path, "node.session.auth.password", (const char *)secret_value) < 0) goto cleanup; ret = 0; cleanup: virObjectUnref(secret); VIR_FREE(secret_value); return ret; }
static int virStorageBackendISCSISetAuth(const char *portal, virConnectPtr conn, virStoragePoolSourcePtr source) { virSecretPtr secret = NULL; unsigned char *secret_value = NULL; virStorageAuthDefPtr authdef = source->auth; int ret = -1; char uuidStr[VIR_UUID_STRING_BUFLEN]; if (!authdef || authdef->authType == VIR_STORAGE_AUTH_TYPE_NONE) return 0; VIR_DEBUG("username='******' authType=%d secretType=%d", authdef->username, authdef->authType, authdef->secretType); if (authdef->authType != VIR_STORAGE_AUTH_TYPE_CHAP) { virReportError(VIR_ERR_XML_ERROR, "%s", _("iscsi pool only supports 'chap' auth type")); return -1; } if (!conn) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("iscsi 'chap' authentication not supported " "for autostarted pools")); return -1; } if (authdef->secretType == VIR_STORAGE_SECRET_TYPE_UUID) secret = virSecretLookupByUUID(conn, authdef->secret.uuid); else secret = virSecretLookupByUsage(conn, VIR_SECRET_USAGE_TYPE_ISCSI, authdef->secret.usage); if (secret) { size_t secret_size; secret_value = conn->secretDriver->secretGetValue(secret, &secret_size, 0, VIR_SECRET_GET_VALUE_INTERNAL_CALL); if (!secret_value) { if (authdef->secretType == VIR_STORAGE_SECRET_TYPE_UUID) { virUUIDFormat(authdef->secret.uuid, uuidStr); virReportError(VIR_ERR_INTERNAL_ERROR, _("could not get the value of the secret " "for username %s using uuid '%s'"), authdef->username, uuidStr); } else { virReportError(VIR_ERR_INTERNAL_ERROR, _("could not get the value of the secret " "for username %s using usage value '%s'"), authdef->username, authdef->secret.usage); } goto cleanup; } } else { if (authdef->secretType == VIR_STORAGE_SECRET_TYPE_UUID) { virUUIDFormat(authdef->secret.uuid, uuidStr); virReportError(VIR_ERR_NO_SECRET, _("no secret matches uuid '%s'"), uuidStr); } else { virReportError(VIR_ERR_NO_SECRET, _("no secret matches usage value '%s'"), authdef->secret.usage); } goto cleanup; } if (virISCSINodeUpdate(portal, source->devices[0].path, "node.session.auth.authmethod", "CHAP") < 0 || virISCSINodeUpdate(portal, source->devices[0].path, "node.session.auth.username", authdef->username) < 0 || virISCSINodeUpdate(portal, source->devices[0].path, "node.session.auth.password", (const char *)secret_value) < 0) goto cleanup; ret = 0; cleanup: virObjectUnref(secret); VIR_FREE(secret_value); return ret; }
static int virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr ptr, virConnectPtr conn, virStoragePoolObjPtr pool) { int ret = -1; int r = 0; unsigned char *secret_value = NULL; size_t secret_value_size; char *rados_key = NULL; virBuffer mon_host = VIR_BUFFER_INITIALIZER; virSecretPtr secret = NULL; char secretUuid[VIR_UUID_STRING_BUFLEN]; size_t i; char *mon_buff = NULL; const char *client_mount_timeout = "30"; const char *mon_op_timeout = "30"; const char *osd_op_timeout = "30"; VIR_DEBUG("Found Cephx username: %s", pool->def->source.auth.cephx.username); if (pool->def->source.auth.cephx.username != NULL) { VIR_DEBUG("Using cephx authorization"); r = rados_create(&ptr->cluster, pool->def->source.auth.cephx.username); if (r < 0) { virReportSystemError(-r, "%s", _("failed to initialize RADOS")); goto cleanup; } if (!conn) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("'ceph' authentication not supported " "for autostarted pools")); return -1; } if (pool->def->source.auth.cephx.secret.uuidUsable) { virUUIDFormat(pool->def->source.auth.cephx.secret.uuid, secretUuid); VIR_DEBUG("Looking up secret by UUID: %s", secretUuid); secret = virSecretLookupByUUIDString(conn, secretUuid); } else if (pool->def->source.auth.cephx.secret.usage != NULL) { VIR_DEBUG("Looking up secret by usage: %s", pool->def->source.auth.cephx.secret.usage); secret = virSecretLookupByUsage(conn, VIR_SECRET_USAGE_TYPE_CEPH, pool->def->source.auth.cephx.secret.usage); } if (secret == NULL) { if (pool->def->source.auth.cephx.secret.uuidUsable) { virReportError(VIR_ERR_NO_SECRET, _("no secret matches uuid '%s'"), secretUuid); } else { virReportError(VIR_ERR_NO_SECRET, _("no secret matches usage value '%s'"), pool->def->source.auth.cephx.secret.usage); } goto cleanup; } secret_value = conn->secretDriver->secretGetValue(secret, &secret_value_size, 0, VIR_SECRET_GET_VALUE_INTERNAL_CALL); if (!secret_value) { if (pool->def->source.auth.cephx.secret.uuidUsable) { virReportError(VIR_ERR_INTERNAL_ERROR, _("could not get the value of the secret " "for username '%s' using uuid '%s'"), pool->def->source.auth.cephx.username, secretUuid); } else { virReportError(VIR_ERR_INTERNAL_ERROR, _("could not get the value of the secret " "for username '%s' using usage value '%s'"), pool->def->source.auth.cephx.username, pool->def->source.auth.cephx.secret.usage); } goto cleanup; } base64_encode_alloc((char *)secret_value, secret_value_size, &rados_key); memset(secret_value, 0, secret_value_size); if (rados_key == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("failed to decode the RADOS key")); goto cleanup; } VIR_DEBUG("Found cephx key: %s", rados_key); if (rados_conf_set(ptr->cluster, "key", rados_key) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to set RADOS option: %s"), "rados_key"); goto cleanup; } memset(rados_key, 0, strlen(rados_key)); if (rados_conf_set(ptr->cluster, "auth_supported", "cephx") < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to set RADOS option: %s"), "auth_supported"); goto cleanup; } } else { VIR_DEBUG("Not using cephx authorization"); if (rados_create(&ptr->cluster, NULL) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("failed to create the RADOS cluster")); goto cleanup; } if (rados_conf_set(ptr->cluster, "auth_supported", "none") < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to set RADOS option: %s"), "auth_supported"); goto cleanup; } } VIR_DEBUG("Found %zu RADOS cluster monitors in the pool configuration", pool->def->source.nhost); for (i = 0; i < pool->def->source.nhost; i++) { if (pool->def->source.hosts[i].name != NULL && !pool->def->source.hosts[i].port) { virBufferAsprintf(&mon_host, "%s:6789,", pool->def->source.hosts[i].name); } else if (pool->def->source.hosts[i].name != NULL && pool->def->source.hosts[i].port) { virBufferAsprintf(&mon_host, "%s:%d,", pool->def->source.hosts[i].name, pool->def->source.hosts[i].port); } else { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("received malformed monitor, check the XML definition")); } } if (virBufferError(&mon_host)) { virReportOOMError(); goto cleanup; } mon_buff = virBufferContentAndReset(&mon_host); VIR_DEBUG("RADOS mon_host has been set to: %s", mon_buff); if (rados_conf_set(ptr->cluster, "mon_host", mon_buff) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to set RADOS option: %s"), "mon_host"); goto cleanup; } /* * Set timeout options for librados. * In case the Ceph cluster is down libvirt won't block forever. * Operations in librados will return -ETIMEDOUT when the timeout is reached. */ VIR_DEBUG("Setting RADOS option client_mount_timeout to %s", client_mount_timeout); rados_conf_set(ptr->cluster, "client_mount_timeout", client_mount_timeout); VIR_DEBUG("Setting RADOS option rados_mon_op_timeout to %s", mon_op_timeout); rados_conf_set(ptr->cluster, "rados_mon_op_timeout", mon_op_timeout); VIR_DEBUG("Setting RADOS option rados_osd_op_timeout to %s", osd_op_timeout); rados_conf_set(ptr->cluster, "rados_osd_op_timeout", osd_op_timeout); ptr->starttime = time(0); r = rados_connect(ptr->cluster); if (r < 0) { virReportSystemError(-r, _("failed to connect to the RADOS monitor on: %s"), mon_buff); goto cleanup; } ret = 0; cleanup: VIR_FREE(secret_value); VIR_FREE(rados_key); if (secret != NULL) virSecretFree(secret); virBufferFreeAndReset(&mon_host); VIR_FREE(mon_buff); return ret; }