[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authenticatio
From: |
Jeff Cody |
Subject: |
Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme |
Date: |
Tue, 24 Apr 2018 14:26:21 -0400 |
User-agent: |
Mutt/1.5.24 (2015-08-30) |
On Fri, Apr 20, 2018 at 04:39:02PM +0200, Markus Armbruster wrote:
> Kevin Wolf <address@hidden> writes:
>
> > Am 18.04.2018 um 17:06 hat Markus Armbruster geschrieben:
> >> Kevin Wolf <address@hidden> writes:
> >>
> >> > The legacy command line syntax supports a "password-secret" option that
> >> > allows to pass an authentication key to Ceph. This was not supported in
> >> > QMP so far.
> >>
> >> We tried during development of v2.9.0 (commit 0a55679b4a5), but reverted
> >> before the release:
> >>
> >> commit 464444fcc161284ac0e743b99251debc297d5236
> >> Author: Markus Armbruster <address@hidden>
> >> Date: Tue Mar 28 10:56:06 2017 +0200
> >>
> >> rbd: Revert -blockdev and -drive parameter auth-supported
> >>
> >> This reverts half of commit 0a55679. We're having second thoughts on
> >> the QAPI schema (and thus the external interface), and haven't reached
> >> consensus, yet. Issues include:
> >>
> >> * The implementation uses deprecated rados_conf_set() key
> >> "auth_supported". No biggie.
> >>
> >> * The implementation makes -drive silently ignore invalid parameters
> >> "auth" and "auth-supported.*.X" where X isn't "auth". Fixable (in
> >> fact I'm going to fix similar bugs around parameter server), so
> >> again no biggie.
> >>
> >> * BlockdevOptionsRbd member @password-secret applies only to
> >> authentication method cephx. Should it be a variant member of
> >> RbdAuthMethod?
> >>
> >> * BlockdevOptionsRbd member @user could apply to both methods cephx
> >> and none, but I'm not sure it's actually used with none. If it
> >> isn't, should it be a variant member of RbdAuthMethod?
> >>
> >> * The client offers a *set* of authentication methods, not a list.
> >> Should the methods be optional members of BlockdevOptionsRbd instead
> >> of members of list @auth-supported? The latter begs the question
> >> what multiple entries for the same method mean. Trivial question
> >> now that RbdAuthMethod contains nothing but @type, but less so when
> >> RbdAuthMethod acquires other members, such the ones discussed above.
> >>
> >> * How BlockdevOptionsRbd member @auth-supported interacts with
> >> settings from a configuration file specified with @conf is
> >> undocumented. I suspect it's untested, too.
> >>
> >> Let's avoid painting ourselves into a corner now, and revert the
> >> feature for 2.9.
> >
> > We tried to address all of these points in the schema of this RFC. Maybe
> > things become easier if we compromise on some.
> >
> >> Note that users can still configure authentication methods with a
> >> configuration file. They probably do that anyway if they use Ceph
> >> outside QEMU as well.
> >
> > This solution that we originally intended to offer was dismissed by
> > libvirt as unpractical: libvirt allows the user to specify both a config
> > file and a key, and if it wanted to use a config file to pass the key,
> > it would have to create a merged config file and keep it sync with the
> > user config file at all times. Understandable that they want to avoid
> > this.
> >
> >> Further note that this doesn't affect use of key "auth-supported" in
> >> -drive file=rbd:...:key=value.
> >>
> >> qemu_rbd_array_opts()'s parameter @type now must be RBD_MON_HOST,
> >> which is silly. This will be cleaned up shortly.
> >>
> >> Signed-off-by: Markus Armbruster <address@hidden>
> >> Reviewed-by: Max Reitz <address@hidden>
> >> Reviewed-by: Eric Blake <address@hidden>
> >> Reviewed-by: Jeff Cody <address@hidden>
> >> Message-id: address@hidden
> >> Signed-off-by: Jeff Cody <address@hidden>
> >>
> >> > This patch introduces authentication options in the QAPI schema, makes
> >> > them do the corresponding rados_conf_set() calls and adds compatibility
> >> > code that translates the old "password-secret" option both for opening
> >>
> >> Suggest 'the old "password-secret" command line option parameter'.
> >>
> >> > and creating images to the new set of options.
> >> >
> >> > Note that the old option didn't allow to explicitly specify the set of
> >>
> >> Likewise, 'the old option parameter'.
> >>
> >> > allowed authentication schemes. The compatibility code assumes that if
> >> > "password-secret" is given, only the cephx scheme is allowed. If it's
> >> > missing, both none and cephx are allowed because the configuration file
> >> > could still provide a key.
> >>
> >> This is a bit terse for readers who aren't familiar with the way things
> >> work now (or have since forgotten pretty much everything about it, like
> >> me).
> >>
> >> Perhaps spelling out how the compatibility code translates the old
> >> option parameter to BlockdevOptionsRbd would help.
> >>
> >> > Signed-off-by: Kevin Wolf <address@hidden>
> >> > ---
> >> >
> >> > This doesn't actually work correctly yet because the way that options
> >> > are passed through the block layer (QAPI -> QemuOpts -> QDict). Before
> >> > we fix or hack around this, let's make sure this is the schema that we
> >> > want.
> >>
> >> Makes sense.
> >>
> >> > The two known problems are:
> >> >
> >> > 1. QDict *options in qemu_rbd_open() may contain options either in their
> >> > proper QObject types (if passed from blockdev-add) or as strings
> >> > (-drive). Both forms can be mixed in the same options QDict.
> >>
> >> Remind me, how can such a mix happen?
> >
> > The way I'm aware of is that you use blockdev-add, so you get the real
> > types for some options, and then the block layer adds strings for
> > default values.
>
> I see.
>
> >> > rbd uses the keyval visitor to convert the options into a QAPI
> >> > object. This means that it requires all options to be strings. This
> >> > patch, however, introduces a bool property, so the visitor breaks
> >> > when it gets its input from blockdev-add.
> >> >
> >> > Options to hack around the problem:
> >> >
> >> > a. Do an extra conversion step or two and go through QemuOpts like
> >> > some other block drivers. When I offered something like this to
> >> > Markus a while ago in a similar case, he rejected the idea.
> >>
> >> Going through QemuOpts just to get rid of strings is a bit like going
> >> down Niagara Falls in a barrel just to get rid of sleepiness: it'll do
> >> that, sure, but it's probably not all it'll do.
> >
> > Nice comparison. I tend to agree, though there is much more precedence
> > for this one than for all other options. Almost all block drivers use
> > QemuOpts to parse their driver-specific options from the QDict.
>
> For historical reasons. If I remember correctly, QemuOpts got there
> first, QDict was spliced in later.
>
> >> > b. Introduce a qdict_stringify_entries() that just does what its name
> >> > says. It would be called before the running keyval visitor so that
> >> > only strings will be present in the QDict.
> >>
> >> Precedence: a bunch of other QDict operations that are used only by the
> >> block layer. One more won't make a difference, I guess.
> >>
> >> Aside: I'm tempted to move them out of qdict.h to reduce the temptation
> >> to use them outside the block layer.
> >
> > Unrelated cleanup, but seems reasonable. block/qdict.h?
>
> Works for me. No rush.
>
> >> > c. Do a local one-off hack that checks if the entry with the key
> >> > "auth-none" is a QBool, and if so, overwrite it with a string. The
> >> > problem will reappear with the next non-string option.
> >>
> >> Defensible only if we're fairly confident such options will remain rare.
> >>
> >> > (d. Get rid of the QDict detour and work only with QAPI objects
> >> > everywhere. Support rbd authentication only in QEMU 4.0.)
> >>
> >> This is of course the proper solution, but it's a big project that will
> >> take time. The occasional stop gaps are unavoidable. We just need to
> >> take care not to spend all of our cycles on stop gaps, and none on
> >> actual progress.
> >>
> >> e. Make the keyval visitor accept scalars other than strings.
> >>
> >> More efficient than b., doubt it matters. Complicates the visitor.
> >> Harder to back out than b. when we no longer need it.
> >>
> >> I'm leaning towards b.
> >
> > Okay, that's what I was leaning towards, too.
>
> Good.
>
> >> > 2. The proposed schema allows 'auth-cephx': {} as a valid option with
> >> > the meaning that the cephx authentication scheme is enabled, but no
> >> > key is given (e.g. it is taken from the config file).
> >>
> >> Apropos config file: we need to be careful to maintain the QAPI schema's
> >> promise that "Values in the configuration file will be overridden by
> >> options specified via QAPI."
> >
> > Yes, though it's made a bit easier by the fact that most options are
> > implemented with a rados_conf_set() call. If you call the function, you
> > override the config, if not, you don't.
>
> Good.
>
> As mentioned in my reply to Dan, the config file can't serve as stable
> interface here: we break it whenever we add options to QAPI. Can't see
> anything we could do but document the issue.
>
> >> > However, an empty dict cannot currently be represented by flattened
> >> > QDicts.
> >>
> >> Flattening a QDict moves nested scalars to the root (with dotted keys),
> >> and drops nested non-scalars, i.e. QDict, QList. A nested empty QDict
> >> (or QList) vanishes without trace.
> >>
> >> > We need to find a way to enable this. I think this will be
> >> > externally visible because it directly translates into the dotted
> >> > syntax of -blockdev, so we may want to be careful.
> >>
> >> Quote keyval.c:
> >>
> >> * Design flaw: there is no way to denote an empty array or non-root
> >> * object. While interpreting "key absent" as empty seems natural
> >> * (removing a key-val from the input string removes the member when
> >> * there are more, so why not when it's the last), it doesn't work:
> >> * "key absent" already means "optional object/array absent", which
> >> * isn't the same as "empty object/array present".
> >>
> >> Getting that syntax right was hairy (you'll probably remember the
> >> lengthy e-mail discussions). I'm reluctant to revisit it. We concluded
> >> back then that dotted key syntax capable of expressing arbitrary JSON
> >> wasn't in the cards, but that the cases it can't do are so exotic that
> >> users should just fall back to JSON. And that would be my advice here.
> >>
> >> Can we design a schema that avoids this case? Let's see below.
> >
> > Can we design such a schema? Yes.
> >
> > Will we like it enough to accept it as a compromise? Maybe.
>
> That's fine. We explore the design space, and pick what we hate least.
> This RFC is a fine start.
>
> >> > Any thoughts on the proposed QAPI schema or the two implementation
> >> > problems are welcome.
> >> >
> >> > qapi/block-core.json | 22 +++++++++++
> >> > block/rbd.c | 102
> >> > ++++++++++++++++++++++++++++++++++++++-------------
> >> > 2 files changed, 99 insertions(+), 25 deletions(-)
> >> >
> >> > diff --git a/qapi/block-core.json b/qapi/block-core.json
> >> > index c50517bff3..d5ce588add 100644
> >> > --- a/qapi/block-core.json
> >> > +++ b/qapi/block-core.json
> >> > @@ -3170,6 +3170,19 @@
> >> >
> >> >
> >> > ##
> >> > +# @RbdAuthCephx:
> >> > +#
> >> > +# @key-secret: ID of a QCryptoSecret object providing a key for
> >> > cephx
> >> > +# authentication. If not specified, a key from the
> >> > +# specified configuration file, or the system
> >> > default
> >> > +# configuration is used, if present.
> >> > +#
> >> > +# Since: 2.13
> >> > +##
> >> > +{ 'struct': 'RbdAuthCephx',
> >> > + 'data': { '*key-secret': 'str' } }
> >> > +
> >> > +##
> >> > # @BlockdevOptionsRbd:
> >> > #
> >> > # @pool: Ceph pool name.
> >> > @@ -3184,6 +3197,13 @@
> >> > #
> >> > # @user: Ceph id name.
> >> > #
> >> > +# @auth-none: true if connecting to a server without
> >> > authentication
> >> > +# should be allowed (default: false; since 2.13)
> >> > +#
> >> > +# @auth-cephx: Configuration for cephx authentication if
> >> > specified. If
> >> > +# not specified, cephx authentication is not
> >> > allowed.
> >> > +# (since 2.13)
> >> > +#
> >> > # @server: Monitor host address and port. This maps
> >> > # to the "mon_host" Ceph option.
> >> > #
> >> > @@ -3195,6 +3215,8 @@
> >> > '*conf': 'str',
> >> > '*snapshot': 'str',
> >> > '*user': 'str',
> >> > + '*auth-none': 'bool',
> >> > + '*auth-cephx': 'RbdAuthCephx',
> >> > '*server': ['InetSocketAddressBase'] } }
> >> >
> >> > ##
> >>
> >> Two new optional members @auth-none, @auth-cephx.
> >>
> >> For backwards compatibility, behavior needs to remain unchanged when
> >> both are absent. What is the behavior we need to preserve? Config
> >> file, then default?
> >
> > Yes. (rados_conf_set("auth_client_required") is not called at all.)
> >
> >> The schema permits four cases, which get translated to an auth client
> >> required setting by qemu_rbd_set_auth(), visible below:
> >>
> >> (1) just auth-none: we set auth_client_required to "none"
> >>
> >> (2) just auth-cephx: we set auth_client_required to "cephx"
> >>
> >> (3) both: we set auth_client_required to "none;cephx", which I can't
> >> find in the documentation right now, but according to my notes means
> >> "either method"
> >
> > The state of the Ceph documentation indeed wasn't very helpful. On the
> > other hand, I'm afraid we're not in a position to complain about bad
> > documentation...
>
> Right on both counts.
>
> >> (4) neither: rejected with "No authentication scheme allowed"
> >> Uh, why isn't this a compatibility break? Or am I confused?
> >
> > It is, and that is one of the reasons why this patch is broken. I failed
> > to mention this in the commit message, but I replied to the patch the
> > next day to add this.
>
> You mean I'm supposed to read the whole thread before I start posting to
> it?!?
>
> >> When auth-cephx is present, we get subcases
> >>
> >> (2a) and (3a) key-secret present: key is in the QCryptoSecret named, and
> >> we set
> >>
> >> (2b) and (3b) key-secret absent: key must be provided some other way,
> >> say in a configuration file, default keyring, whatever, or else
> >> we'll fail somehow, I guess
> >>
> >> Related: existing BlockdevOptionsRbd member @user. As far as I know,
> >> it's meaningless with auth-none.
> >
> > I don't know otherwise and suspect you are right, but Jeff and I
> > couldn't find any definite confirmation for this assumption, so we left
> > it where it is instead of moving it into RbdAuthCephx.
>
> I pestered Jason Dillaman about this stuff back then, and he explained
>
> If the auth is set to none, the user is technically irreverent. I
> can run a command like "rbd --id this_user_does_not_exist rm
> image_name" and it will succeed if cephx is disabled on the server.
>
> Off list, Jeff was cc'ed, you weren't.
>
> >> Ways to avoid the troublesome auth-cephx: {}:
> >>
> >> (A) Make auth-cephx a bool, rely on the other ways to provide the key
> >>
> >> (B) Make auth-cephx a bool and add the @key-secret member next to it
> >>
> >> Like @user, the member is meaningless with auth-none.
> >>
> >> (C) Make auth-cephx.key-secret a mandatory StrOrNull
> >>
> >> Should take care of "vanishes on flattening" problem, but dotted key
> >> syntax is still screwed: since any value is a valid string, there's
> >> none left for null. My take would be that if you want to say
> >> auth-cephx.key-secret: {}, you get to say it in JSON.
> >>
> >> Aside: check_alternate() tries to catch such alternates, but we
> >> failed to update it when we added first class null. *sigh*
> >>
> >> Which one do you hate least?
> >
> > What should happen with null when you stringify it? If we want to take
> > the options QDict, stringify all entries and run them through the keyval
> > visitor, I'm almost sure that null will be lost.
>
> For the stringify idea to work, the keyval visitor needs to map the
> string right back to the original value.
>
> The keyval visitor currently requires the value to be null, not a
> string.
>
> Therefore, the stringify operation must leave null alone. Not pretty,
> but works.
>
> You might ask why not change the keyval visitor instead so it expects ""
> rather than null. That's no good, because it makes StrOrNull ambiguous.
>
> keyval.c can only create string scalars. I think "use JSON if you want
> to specify null" is still good enough. We can make keyval.c more
> expressive if we need to, but (1) I don't think we should block this
> work on it, and (2) see "hairy" above.
>
> > So (A) doesn't work unless we can specify what "other ways" are that are
> > acceptable for libvirt,
>
> Yes.
>
> > and (C) probably doesn't play well with b. above
> > (the qdict_stringify_entries() for handling mixed type QDicts).
>
> I think it could be done, and tried to sketch how.
>
> > Looks like only (B) is left as viable, so that's automatically the one I
> > hate least of these. If we can fix the problems, I think I'd prefer (C),
> > though.
>
> I could accept (B), in particular since it mirrors existing @user.
>
> I'm happy to help with exploring (C).
>
> What's the next step?
My preference is (B). Primarily because I don't like the idea of breaking
dotted key syntax for null keys. I'd rather see something more verbose like
(B), that can still be navigated correctly both ways.
How about I put together a patch with (B) for an RFC v2?
-Jeff
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, (continued)
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, Kevin Wolf, 2018/04/18
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, Daniel P . Berrangé, 2018/04/18
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, Kevin Wolf, 2018/04/18
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, Daniel P . Berrangé, 2018/04/18
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, Markus Armbruster, 2018/04/20
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, Daniel P . Berrangé, 2018/04/20
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, Markus Armbruster, 2018/04/20
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, Daniel P . Berrangé, 2018/04/20
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, Markus Armbruster, 2018/04/20
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, Markus Armbruster, 2018/04/20
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme,
Jeff Cody <=
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, Kevin Wolf, 2018/04/25
- Re: [Qemu-devel] [RFC][BROKEN] rbd: Allow configuration of authentication scheme, Jeff Cody, 2018/04/27