The branch, master has been updated
via 1f432474c40 manpages/vfs_ceph_new: document fscrypt and keybridge
options
via 29f4d89cb64 vfs_ceph_new: add keybridge and ceph fscrypt support
via 4c25fb47e0b build: add '--with-varlink' configure option
via 665ab9fd609 vfs: add files to access the varlink keybridge API
from 27a77e908d9 WHATSNEW: update with vfs_aio_ratelimit details
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 1f432474c40ff675942ed688357c299eeda4fd7f
Author: John Mulligan <[email protected]>
Date: Fri Aug 29 11:38:34 2025 -0400
manpages/vfs_ceph_new: document fscrypt and keybridge options
Document the option used to enable fscrypt-style subvolume encryption
on cephfs. Document the options used to get key material for fscrypt
using the varlink-based keybridge local RPC protocol.
Signed-off-by: John Mulligan <[email protected]>
Reviewed-by: Gunther Deschner <[email protected]>
Reviewed-by: Anoop C S <[email protected]>
Autobuild-User(master): Anoop C S <[email protected]>
Autobuild-Date(master): Tue Jan 20 06:52:32 UTC 2026 on atb-devel-224
commit 29f4d89cb6467da98ddf45a09d9995c4467a67bc
Author: John Mulligan <[email protected]>
Date: Wed Aug 6 13:32:50 2025 -0400
vfs_ceph_new: add keybridge and ceph fscrypt support
Add support for CephFS's new fscrypt feature. Fetch the key material
using the new keybridge varlink local RPC API.
Adds the following configuration parameters for the vfs_ceph_new module:
```
ceph_new:keybridge socket = unix:/run/keybridge.sock
ceph_new:keybridge scope = mem
ceph_new:keybridge name = test
ceph_new:keybridge kind = B64
ceph_new:fscrypt = keybridge
```
Where the various keybridge parameters configure what keybridge server
to use and what key to fetch. The `ceph_new:fscrypt` parameter defaults to
'disabled' and can be set to 'keybridge'. An enum is used here in case
we ever need to support something other than keybridge in the future.
Pair-Programmed-With: Shachar Sharon <[email protected]>
Signed-off-by: Shachar Sharon <[email protected]>
Signed-off-by: John Mulligan <[email protected]>
Reviewed-by: Gunther Deschner <[email protected]>
Reviewed-by: Anoop C S <[email protected]>
commit 4c25fb47e0b8de7c18bcb8b7409603b9c35e7df7
Author: John Mulligan <[email protected]>
Date: Thu Jun 5 16:47:55 2025 -0400
build: add '--with-varlink' configure option
When building with varlink support, require explicit '--with-varlink'
configure option to be set. If set, allow ceph+fscrypt configuration.
Pair-Programmed-With: Shachar Sharon <[email protected]>
Signed-off-by: Shachar Sharon <[email protected]>
Signed-off-by: John Mulligan <[email protected]>
Reviewed-by: Gunther Deschner <[email protected]>
Reviewed-by: Anoop C S <[email protected]>
commit 665ab9fd609e08b59e3062bc83f7d016a9d0b40b
Author: John Mulligan <[email protected]>
Date: Thu Jun 5 16:47:10 2025 -0400
vfs: add files to access the varlink keybridge API
Add a pair of helper files that will allow vfs modules to make use of
the keybridge - a varlink API and server that is defined by the sambacc
project. The keybridge server exists to act as a proxy between smbd and
various possible "secrets management" backends. Currently, the sambacc
keybridge server implements a "mem" backend, for testing only, and a
KMIP backend.
Using a local RPC protocol, like varlink + keybridge allows the smbd
side to be very simple and only know how to talk the keybridge API,
versus having to teach it about various other APIs that may need to
make use of things like mTLS.
Furthermore, samba already has an (currently optional) dependency on
libvarlink so adding another use of varlink seems like a fairly
minimal change to samba's set of dependencies. This feature will
not be built on if libvarlink is not enabled. The plan is to add this
to vfs_ceph_new in a future patch.
Signed-off-by: John Mulligan <[email protected]>
Reviewed-by: Gunther Deschner <[email protected]>
Reviewed-by: Anoop C S <[email protected]>
-----------------------------------------------------------------------
Summary of changes:
docs-xml/manpages/vfs_ceph_new.8.xml | 119 +++++++++++++++
source3/modules/varlink_keybridge.c | 228 ++++++++++++++++++++++++++++
source3/modules/varlink_keybridge.h | 82 ++++++++++
source3/modules/vfs_ceph_new.c | 286 ++++++++++++++++++++++++++++++++++-
source3/modules/wscript_build | 10 +-
source3/wscript | 25 ++-
wscript | 5 +
7 files changed, 747 insertions(+), 8 deletions(-)
create mode 100644 source3/modules/varlink_keybridge.c
create mode 100644 source3/modules/varlink_keybridge.h
Changeset truncated at 500 lines:
diff --git a/docs-xml/manpages/vfs_ceph_new.8.xml
b/docs-xml/manpages/vfs_ceph_new.8.xml
index 4c05f9ddd4b..c0ff3e7da30 100644
--- a/docs-xml/manpages/vfs_ceph_new.8.xml
+++ b/docs-xml/manpages/vfs_ceph_new.8.xml
@@ -181,6 +181,125 @@
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>ceph_new:fscrypt = [ disabled | none | keybridge ]</term>
+ <listitem>
+ <para>
+ Configures the CephFS client to enable FSCrypt-style
+ encrypted (sub-)volume support. If enabled, encryption
+ is applied automatically to empty shares and future
+ connections to said share will require FSCrypt with
+ the same key material.
+ </para>
+
+ <itemizedlist>
+ <listitem><para><constant>disabled</constant> (default)
+ - FSCrypt support is disabled.
+ </para></listitem>
+
+ <listitem><para><constant>none</constant> - An alias
+ for <constant>disabled</constant>.
+ </para></listitem>
+
+ <listitem><para><constant>keybridge</constant> - Enable
+ CephFS FSCrypt support using the keybridge RPC API
+ for fetching key material. Setting this option
+ requires that the options
+ <constant>ceph_new:keybridge socket</constant>,
+ <constant>ceph_new:keybridge scope</constant>, and
+ <constant>ceph_new:keybridge name</constant>
+ be specified.
+ </para></listitem>
+ </itemizedlist>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>ceph_new:keybridge socket = type:path</term>
+ <listitem>
+ <para>
+ Configures the CephFS FSCrypt support to communicate
+ with a KeyBridge server listening to the provided
+ socket. The KeyBridge server uses the varlink KeyBridge
+ protocol to fetch key material from one or more
+ key distribution services, such as KMIP for example.
+ </para>
+
+ <para>
+ The only permitted type is <constant>unix</constant>.
+ The path value is a path to a unix domain socket
+ for a keybridge server.
+ For example: unix:/run/keybridge/keybridge.sock
+ </para>
+
+ <para>
+ If specified, this option requires the options
+ <constant>ceph_new:keybridge scope</constant> and
+ <constant>ceph_new:keybridge name</constant>
+ to be specified.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>ceph_new:keybridge scope = scope</term>
+ <listitem>
+ <para>
+ Set the scope value for KeyBridge API requests.
+ The scope identifies a context for keys, typically
+ mapping to a particular backend. The available
+ scope values depend on the configuration of the
+ KeyBridge server.
+ For example: "kmip.testing".
+ </para>
+
+ <para>
+ If specified, this option requires the options
+ <constant>ceph_new:keybridge socket</constant> and
+ <constant>ceph_new:keybridge name</constant>
+ to be specified.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>ceph_new:keybridge name = name</term>
+ <listitem>
+ <para>
+ Set the name value for KeyBridge API requests.
+ The name or identifier for a key, within a scope,
+ that the KeyBridge server will be use to "unlock"
+ the encryption for this share.
+ For example: "volume1".
+ </para>
+
+ <para>
+ If specified, this option requires the options
+ <constant>ceph_new:keybridge socket</constant> and
+ <constant>ceph_new:keybridge scope</constant>
+ to be specified.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>ceph_new:keybridge kind = [ B64 | VALUE ]</term>
+ <listitem>
+ <para>
+ Set the kind of the data field for KeyBridge API
requests.
+ A KeyBridge server is capable of data exchange using
+ either Base64 encoded strings (B64) or plain text
(VALUE).
+ Depending on the scope, a server may be able to
+ fetch key material in one form or the other.
+ Use this option to manually select the data kind.
+ </para>
+
+ <para>
+ If unspecified, B64 will be used.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/source3/modules/varlink_keybridge.c
b/source3/modules/varlink_keybridge.c
new file mode 100644
index 00000000000..38b16163a10
--- /dev/null
+++ b/source3/modules/varlink_keybridge.c
@@ -0,0 +1,228 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Copyright (c) 2025 John Mulligan <[email protected]>
+ *
+ * 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 "includes.h"
+#include "varlink_keybridge.h"
+
+#include <varlink.h>
+
+#define VLKB_PREFIX "[varlink_keybridge] "
+#define KB_DBG_T(...) DEBUG(8, (VLKB_PREFIX __VA_ARGS__))
+#define KB_DBG_I(...) DEBUG(5, (VLKB_PREFIX __VA_ARGS__))
+
+#define DBG_ERR_VLKB(msg, verror) \
+ DBG_ERR(VLKB_PREFIX "%s: %s\n", (msg), (varlink_error_string(verror)))
+
+#define KB_GET "org.samba.containers.keybridge.Get"
+#define KB_F_NAME "name"
+#define KB_F_SCOPE "scope"
+#define KB_F_KIND "kind"
+#define KB_F_ENTRY "entry"
+#define KB_F_DATA "data"
+#define KB_KIND_B64 "B64"
+#define KB_KIND_VALUE "VALUE"
+
+static const char *vlkb_kind_string(enum varlink_keybridge_kind kind)
+{
+ switch (kind) {
+ case VARLINK_KEYBRIDGE_KIND_B64:
+ return KB_KIND_B64;
+ default:
+ return KB_KIND_VALUE;
+ }
+}
+
+static void vlkb_error(struct varlink_keybridge_result *result,
+ const char *msg,
+ VarlinkObject *obj)
+{
+ char *json;
+ long vret = varlink_object_to_json(obj, &json);
+ if (vret < 0) {
+ result->status = VARLINK_KEYBRIDGE_STATUS_FAILURE;
+ result->data = talloc_strdup(result,
+ "varlink_object_to_json failed");
+ return;
+ }
+
+ result->status = VARLINK_KEYBRIDGE_STATUS_ERROR;
+ result->data = talloc_asprintf(result, "%s, object: %s", msg, json);
+ free(json);
+}
+
+static long vlkb_get(VarlinkConnection *conn,
+ const char *error,
+ VarlinkObject *parameters,
+ uint64_t flags,
+ void *userdata)
+{
+ struct varlink_keybridge_result *result = userdata;
+ const char *tmp = NULL;
+ VarlinkObject *entry;
+ enum varlink_keybridge_kind kind = VARLINK_KEYBRIDGE_KIND_DEFAULT;
+ int vret;
+
+ if (error) {
+ vlkb_error(result, error, parameters);
+ goto done;
+ }
+
+ vret = varlink_object_get_object(parameters, KB_F_ENTRY, &entry);
+ if (vret < 0) {
+ vlkb_error(result, "invalid field: " KB_F_ENTRY, parameters);
+ goto done;
+ }
+
+ vret = varlink_object_get_string(entry, KB_F_KIND, &tmp);
+ if (vret < 0) {
+ vlkb_error(result, "invalid field: " KB_F_KIND, entry);
+ goto done;
+ }
+ if (strcmp(KB_KIND_B64, tmp) == 0) {
+ kind = VARLINK_KEYBRIDGE_KIND_B64;
+ } else if (strcmp(KB_KIND_VALUE, tmp) == 0) {
+ kind = VARLINK_KEYBRIDGE_KIND_VALUE;
+ }
+
+ vret = varlink_object_get_string(entry, KB_F_DATA, &tmp);
+ if (vret < 0) {
+ vlkb_error(result, "invalid field: " KB_F_DATA, entry);
+ goto done;
+ }
+ result->data = talloc_strdup(result, tmp);
+ if (result->data == NULL) {
+ DBG_ERR(VLKB_PREFIX "talloc_strdup failed\n");
+ goto done;
+ }
+ result->status = VARLINK_KEYBRIDGE_STATUS_OK;
+ result->kind = kind;
+
+done:
+ return varlink_connection_close(conn);
+}
+
+static long vlkb_wait_for_response(VarlinkConnection *conn)
+{
+ struct timeval tv = {.tv_sec = 5, .tv_usec = 0};
+ int fd = varlink_connection_get_fd(conn);
+ int ret;
+ fd_set rfds;
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ ret = select(fd + 1, &rfds, NULL, NULL, &tv);
+ if (ret == -1) {
+ DBG_ERR(VLKB_PREFIX "select() error: %s\n", strerror(errno));
+ return -VARLINK_ERROR_INVALID_CALL;
+ } else if (ret == 0) {
+ DBG_ERR(VLKB_PREFIX "select() timed out\n");
+ return -VARLINK_ERROR_INVALID_CALL;
+ }
+ return varlink_connection_process_events(conn, 0);
+}
+
+static bool vlkb_entry_get(TALLOC_CTX *mem_ctx,
+ const struct varlink_keybridge_config *kbc,
+ struct varlink_keybridge_result **resp)
+{
+ bool completed = false;
+ VarlinkConnection *conn = NULL;
+ VarlinkObject *params = NULL;
+ struct varlink_keybridge_result *result;
+ long vret;
+
+ KB_DBG_I("calling varlink keybridge get method\n");
+ KB_DBG_T("creating %s arguments object\n", KB_GET);
+ vret = varlink_object_new(¶ms);
+ if (vret < 0) {
+ DBG_ERR_VLKB("varlink_object_new failed", -vret);
+ goto done;
+ }
+ vret = varlink_object_set_string(params, KB_F_NAME, kbc->name);
+ if (vret < 0) {
+ DBG_ERR_VLKB("varlink_object_set_string '" KB_F_NAME "' failed",
+ -vret);
+ goto done;
+ }
+ vret = varlink_object_set_string(params, KB_F_SCOPE, kbc->scope);
+ if (vret < 0) {
+ DBG_ERR_VLKB("varlink_object_set_string '" KB_F_SCOPE
+ "' failed",
+ -vret);
+ goto done;
+ }
+ vret = varlink_object_set_string(params,
+ KB_F_KIND,
+ vlkb_kind_string(kbc->kind));
+ if (vret < 0) {
+ DBG_ERR_VLKB("varlink_object_set_string '" KB_F_KIND "' failed",
+ -vret);
+ goto done;
+ }
+
+ /* set up the varlink connection */
+ KB_DBG_T("creating %s connection\n", KB_GET);
+ vret = varlink_connection_new(&conn, kbc->path);
+ if (vret < 0) {
+ DBG_ERR_VLKB("varlink_connection_new failed", -vret);
+ goto done;
+ }
+
+ KB_DBG_T("creating %s result object\n", KB_GET);
+ result = talloc_zero(mem_ctx, struct varlink_keybridge_result);
+ if (result == NULL) {
+ DBG_ERR(VLKB_PREFIX "talloc_zero failed\n");
+ goto done;
+ }
+ *resp = result;
+
+ KB_DBG_T("performing %s call\n", KB_GET);
+ vret = varlink_connection_call(
+ conn, KB_GET, params, 0, vlkb_get, result);
+ if (vret < 0) {
+ DBG_ERR_VLKB("varlink_connection_call failed", -vret);
+ goto done;
+ }
+ KB_DBG_T("waiting for %s response\n", KB_GET);
+ vret = vlkb_wait_for_response(conn);
+ if (vret < 0) {
+ DBG_ERR_VLKB("vlkb_wait_for_response failed", -vret);
+ goto done;
+ }
+ completed = true;
+
+done:
+ if (params) {
+ varlink_object_unref(params);
+ }
+ if (conn) {
+ varlink_connection_free(conn);
+ }
+ KB_DBG_I("varlink keybridge get method: %s\n",
+ (completed) ? "success" : "failure");
+ return completed;
+}
+
+bool varlink_keybridge_entry_get(TALLOC_CTX *mem_ctx,
+ const struct varlink_keybridge_config *kbc,
+ struct varlink_keybridge_result **resp)
+{
+ return vlkb_entry_get(mem_ctx, kbc, resp);
+}
diff --git a/source3/modules/varlink_keybridge.h
b/source3/modules/varlink_keybridge.h
new file mode 100644
index 00000000000..5bcd0589e36
--- /dev/null
+++ b/source3/modules/varlink_keybridge.h
@@ -0,0 +1,82 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Copyright (c) 2025 John Mulligan <[email protected]>
+ *
+ * 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/>.
+ */
+
+#ifndef _VARLINK_KEYBRIDGE_H
+#define _VARLINK_KEYBRIDGE_H
+/*
+ * The keybridge is a simple varlink based protocol used to fetch
+ * configuration data, in particular key material for encrypted
+ * cephfs, that samba can use when setting up a share.
+ * The keybridge server may or may not be a proxy for more complex
+ * remote protocols that use (m)TLS HTTPS APIs to remote servers.
+ * keybridge aims to hide all that from samba and use a simple
+ * local API that is an existing samba dependency.
+ */
+
+/* kind describes how the data is stored:
+ * DEFAULT - unspecified - typically VALUE
+ * B64 - base64 encoded binary data
+ * VALUE - plain (UTF8) string
+ */
+enum varlink_keybridge_kind {
+ VARLINK_KEYBRIDGE_KIND_DEFAULT = 0,
+ VARLINK_KEYBRIDGE_KIND_B64,
+ VARLINK_KEYBRIDGE_KIND_VALUE
+};
+
+/* status of a keybridge api call */
+enum varlink_keybridge_status {
+ /* protocol/connection error */
+ VARLINK_KEYBRIDGE_STATUS_FAILURE = 0,
+ /* result is successful */
+ VARLINK_KEYBRIDGE_STATUS_OK,
+ /* server returned an error message */
+ VARLINK_KEYBRIDGE_STATUS_ERROR,
+};
+
+/* parameters for an outgoing api Get entry call */
+struct varlink_keybridge_config {
+ /* path to socket with unix: prefix */
+ char *path;
+ /* keybridge scope */
+ char *scope;
+ /* keybridge entry name */
+ char *name;
+ /* keybridge entry kind (data format) */
+ enum varlink_keybridge_kind kind;
+};
+
+/* Get entry call results */
+struct varlink_keybridge_result {
+ enum varlink_keybridge_status status;
+ /* data kind */
+ enum varlink_keybridge_kind kind;
+ /* result data or error string */
+ char *data;
+};
+
+/* Get a requested entry.
+ * returns true if result was populated
+ * result will be assigned a newly allocated result (from mem_ctx)
+ */
+bool varlink_keybridge_entry_get(TALLOC_CTX *mem_ctx,
+ const struct varlink_keybridge_config *kbc,
+ struct varlink_keybridge_result **resp);
+
+#endif /* _VARLINK_KEYBRIDGE_H */
diff --git a/source3/modules/vfs_ceph_new.c b/source3/modules/vfs_ceph_new.c
index 5e9d6add4cc..4a91f55b612 100644
--- a/source3/modules/vfs_ceph_new.c
+++ b/source3/modules/vfs_ceph_new.c
@@ -39,6 +39,11 @@
#include "smbprofile.h"
#include "modules/posixacl_xattr.h"
#include "lib/util/tevent_unix.h"
+#include "lib/util/base64.h"
+#if HAVE_CEPH_FSCRYPT
+#include <linux/fscrypt.h>
+#include "modules/varlink_keybridge.h"
+#endif
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
@@ -93,12 +98,38 @@ static const struct enum_list enum_vfs_cephfs_proxy_vals[]
= {
{-1, NULL}
};
+enum vfs_cephfs_fscrypt_mode {
+ /* no fscrypt */
+ VFS_CEPHFS_FSCRYPT_DISABLED,
+ /* enable fscrypt, get keys from keybridge */
+ VFS_CEPHFS_FSCRYPT_KEYBRIDGE
+};
+
+static const struct enum_list enum_vfs_cephfs_fscrypt_vals[] = {
+ {VFS_CEPHFS_FSCRYPT_DISABLED, "disabled"},
+ {VFS_CEPHFS_FSCRYPT_DISABLED, "none"},
+ {VFS_CEPHFS_FSCRYPT_KEYBRIDGE, "keybridge"},
+};
+
+struct vfs_ceph_fscrypt_key {
+ /* TODO: need a key type or expected length to validate the data? */
+ DATA_BLOB blob;
+};
+
+#define FS_KEY_DATA(kp) (char *)((kp)->blob.data)
+#define FS_KEY_LEN(kp) ((kp)->blob.length)
+
#define CEPH_FN(_name) typeof(_name) *_name ## _fn
struct vfs_ceph_config {
#ifdef HAVE_CEPH_ASYNCIO
struct tevent_threaded_context *tctx;
#endif
+#if HAVE_CEPH_FSCRYPT
--
Samba Shared Repository