diff mbox

[for-2.9,4/5] rbd: Peel off redundant RbdAuthMethod wrapper struct

Message ID 1490266548-22500-5-git-send-email-armbru@redhat.com
State New
Headers show

Commit Message

Markus Armbruster March 23, 2017, 10:55 a.m. UTC
BlockdevOptionsRbd member auth-supported is a list of struct
RbdAuthMethod, whose only member is enum RbdAuthSupport.  There is no
reason for wrapping the enum in a struct.  Delete the wrapper, and
rename the enum.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block/rbd.c          |  2 +-
 qapi/block-core.json | 15 ++-------------
 2 files changed, 3 insertions(+), 14 deletions(-)

Comments

Eric Blake March 23, 2017, 6:10 p.m. UTC | #1
On 03/23/2017 05:55 AM, Markus Armbruster wrote:
> BlockdevOptionsRbd member auth-supported is a list of struct
> RbdAuthMethod, whose only member is enum RbdAuthSupport.  There is no
> reason for wrapping the enum in a struct.

Well, the previous patch removed the QemuOpts madness as a technical
reason that required the wrapper, leaving nothing else technically using
it at the moment.  But there's still the design to think about...

>  Delete the wrapper, and
> rename the enum.

This patch changes the QMP wire format. It MUST go in 2.9, otherwise,
we've baked in the insanity; that is, if we decide it is insanity [1]

> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block/rbd.c          |  2 +-
>  qapi/block-core.json | 15 ++-------------
>  2 files changed, 3 insertions(+), 14 deletions(-)
> 

> +++ b/qapi/block-core.json
> @@ -2601,25 +2601,14 @@
>  
>  
>  ##
> -# @RbdAuthSupport:
> -#
> -# An enumeration of RBD auth support
> -#
> -# Since: 2.9
> -##
> -{ 'enum': 'RbdAuthSupport',
> -  'data': [ 'cephx', 'none' ] }
> -
> -
> -##
>  # @RbdAuthMethod:
>  #
>  # An enumeration of rados auth_supported types
>  #
>  # Since: 2.9
>  ##
> -{ 'struct': 'RbdAuthMethod',
> -  'data': { 'auth': 'RbdAuthSupport' } }
> +{ 'enum': 'RbdAuthMethod',
> +  'data': [ 'cephx', 'none' ] }

Changes BlockdevOptionsRbd from:

..., "auth-supported": [ { "auth": "none" } ],

to the potentially much nicer:

..., "auth-supported": [ "none" ],

[1] But what if we want to make auth-supported be an array of flat
unions, where 'auth' is the discriminator that determines if additional
members are needed?  In other words, the existing API would allow:

"auth-supported": [ { "auth": "cephx" },
                    { "auth": "new", "password-id": "foo" } ]

for specifying a new auth type 'new' that comes with an associated
'password-id' field for looking up a corresponding 'secret' object used
for retrieving the associated password when using that type of
authorization.  In that scenario, RbdAuthMethod would look more like
this pseudo-qapi:

{ 'union': 'RbdAuthMethod', 'base': { 'auth': 'RbdAuthSupport' },
  'discriminator': 'auth',
  'data': { 'none': {},
            'cephx': {},
            'new': { 'password-id': 'str' } } }

Assuming we are okay with not needing to extend the current one-member
RbdAuthMethod struct into a flat union, then this patch is fine, and you
can add:

Reviewed-by: Eric Blake <eblake@redhat.com>

But if you think the flat union expansion path may ever prove useful,
then maybe we don't want this patch after all.
Kevin Wolf March 23, 2017, 8:52 p.m. UTC | #2
Am 23.03.2017 um 11:55 hat Markus Armbruster geschrieben:
> BlockdevOptionsRbd member auth-supported is a list of struct
> RbdAuthMethod, whose only member is enum RbdAuthSupport.  There is no
> reason for wrapping the enum in a struct.  Delete the wrapper, and
> rename the enum.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Eric Blake March 23, 2017, 8:59 p.m. UTC | #3
On 03/23/2017 01:10 PM, Eric Blake wrote:

>>  # @RbdAuthMethod:
>>  #
>>  # An enumeration of rados auth_supported types
>>  #
>>  # Since: 2.9
>>  ##
>> -{ 'struct': 'RbdAuthMethod',
>> -  'data': { 'auth': 'RbdAuthSupport' } }
>> +{ 'enum': 'RbdAuthMethod',
>> +  'data': [ 'cephx', 'none' ] }
> 
> Changes BlockdevOptionsRbd from:
> 
> ..., "auth-supported": [ { "auth": "none" } ],

Another question - why does auth-supported take an array?  Can you
really pass both 'none' and 'cephx' at the same time? Or can you only
pass an array of at most one element, at which point why is it an array?
Eric Blake March 23, 2017, 9:43 p.m. UTC | #4
On 03/23/2017 03:59 PM, Eric Blake wrote:
> On 03/23/2017 01:10 PM, Eric Blake wrote:
> 
>>>  # @RbdAuthMethod:
>>>  #
>>>  # An enumeration of rados auth_supported types
>>>  #
>>>  # Since: 2.9
>>>  ##
>>> -{ 'struct': 'RbdAuthMethod',
>>> -  'data': { 'auth': 'RbdAuthSupport' } }
>>> +{ 'enum': 'RbdAuthMethod',
>>> +  'data': [ 'cephx', 'none' ] }
>>
>> Changes BlockdevOptionsRbd from:
>>
>> ..., "auth-supported": [ { "auth": "none" } ],
> 
> Another question - why does auth-supported take an array?  Can you
> really pass both 'none' and 'cephx' at the same time? Or can you only
> pass an array of at most one element, at which point why is it an array?

In fact, the more I look at this, the more I wonder if we really want
'auth' to be a flat union and move the 'password-secret' key to be part
of the cephx authorization scheme, since 'password-secret' only makes
sense with 'cephx', and not with 'none'.  Jeff pointed out to me that
libvirt is currently passing both at once; qemuBuildRBDSecinfoURI():

static int
qemuBuildRBDSecinfoURI(virBufferPtr buf,
                       qemuDomainSecretInfoPtr secinfo)
{
    char *base64secret = NULL;

    if (!secinfo) {
        virBufferAddLit(buf, ":auth_supported=none");
        return 0;
    }

    switch ((qemuDomainSecretInfoType) secinfo->type) {
    case VIR_DOMAIN_SECRET_INFO_TYPE_PLAIN:
        if (!(base64secret = virStringEncodeBase64(secinfo->s.plain.secret,

secinfo->s.plain.secretlen)))
            return -1;
        virBufferEscape(buf, '\\', ":", ":id=%s",
secinfo->s.plain.username);
        virBufferEscape(buf, '\\', ":",
                        ":key=%s:auth_supported=cephx\\;none",
                        base64secret);

But maybe what that _really_ means is that librados is letting us say
"I'd really prefer cephx authorization, and here's my key; but if you
can't honor that, I'm also okay with a fallback to no auth".

That feels wrong to me. If you've gone to the bother of providing an
encryption key, falling back to none should probably be an error.

So my proposal is to have:

{ 'enum': 'RbdAuthSupport', 'data': [ 'cephx', 'none' ] }
{ 'struct': 'RbdAuthNone', 'data': { } }
{ 'struct': 'RbdAuthCephx', 'data': { 'password-secret': 'str' } }
{ 'union', 'RbdAuthMethod', 'base': { 'type': 'RbdAuthSupport' },
  'discriminator': 'type',
  'data': { 'none': 'RbdAuthNone',
            'cephx': 'RbdAuthCephx' } } }
{ 'struct': 'BlockdevOptionsRbd',
  'data': { 'pool': 'str',
            'image': 'str',
            '*conf': 'str',
            '*snapshot': 'str',
            '*user': 'str',
            '*server': ['InetSocketAddress'],
            '*auth': 'RbdAuthMethod' } }

so that you pass at most one auth method, looking like:

..., "image": ..., "auth": { "type": "none" }

or like:

..., "image": ..., "auth": { "type": "cephx", "password-secret": "..." }

note that password-secret is NOT at the same level as image, so from the
command line, supporting either old-style insecure 'key=' or new-style
'password-secret' at the top-level of the QemuOpts will have to have
glue code that maps it to the right nested location within the QAPI
type.  If we like it, we'd have to get it implemented before 2.9 bakes
in any other design.

We'd still have to allow libvirt's use of
":key=...:auth_supported=cephx\\;none" on the command line, but from the
QMP side, we would support exactly one auth method, and libvirt will be
updated to match when it starts targetting blockdev-add instead of
legacy command line.

If librados really needs 'cephx;none' any time cephx authorization is
requested, then even though the QMP only requests 'cephx', we can still
map it to 'cephx;none' in qemu - but I'm hoping that setting
auth_supported=cephx rather than auth_supported=cephx;none on the
librados side gives us what we (and libvirt) really want in the first place.

Jeff or Josh, if you could chime in, that would be helpful.
Eric Blake March 23, 2017, 9:56 p.m. UTC | #5
On 03/23/2017 04:43 PM, Eric Blake wrote:

> We'd still have to allow libvirt's use of
> ":key=...:auth_supported=cephx\\;none" on the command line, but from the
> QMP side, we would support exactly one auth method, and libvirt will be
> updated to match when it starts targetting blockdev-add instead of
> legacy command line.
> 
> If librados really needs 'cephx;none' any time cephx authorization is
> requested, then even though the QMP only requests 'cephx', we can still
> map it to 'cephx;none' in qemu - but I'm hoping that setting
> auth_supported=cephx rather than auth_supported=cephx;none on the
> librados side gives us what we (and libvirt) really want in the first place.

Or, if it becomes something that libvirt wants to allow users to tune in
their XML (right now, users don't get a choice, they get either 'none'
or 'cephx;none'), a forward-compatible solution under my QMP proposal
would be to have qemu add a third enum state, "none", "cephx", and
"cephx-no-fallback".

On the other hand, if supporting multiple methods at once makes sense
(say librados adds a 'cephy' method, and that users could legitimately
use both 'cephx;cephy' and 'cephy;cephx' with different behaviors), then
keeping auth as an array of instances of a simple flat union scales
nicer than having to add a combinatorial explosion of branches to the
flat union to cover every useful combination of auth_supported methods.
Maybe I'm overthinking it.

> 
> Jeff or Josh, if you could chime in, that would be helpful.
>
Jeff Cody March 24, 2017, 3:55 a.m. UTC | #6
On Thu, Mar 23, 2017 at 04:56:30PM -0500, Eric Blake wrote:
> On 03/23/2017 04:43 PM, Eric Blake wrote:
> 
> > We'd still have to allow libvirt's use of
> > ":key=...:auth_supported=cephx\\;none" on the command line, but from the
> > QMP side, we would support exactly one auth method, and libvirt will be
> > updated to match when it starts targetting blockdev-add instead of
> > legacy command line.
> > 
> > If librados really needs 'cephx;none' any time cephx authorization is
> > requested, then even though the QMP only requests 'cephx', we can still
> > map it to 'cephx;none' in qemu - but I'm hoping that setting
> > auth_supported=cephx rather than auth_supported=cephx;none on the
> > librados side gives us what we (and libvirt) really want in the first place.
> 
> Or, if it becomes something that libvirt wants to allow users to tune in
> their XML (right now, users don't get a choice, they get either 'none'
> or 'cephx;none'), a forward-compatible solution under my QMP proposal
> would be to have qemu add a third enum state, "none", "cephx", and
> "cephx-no-fallback".
> 
> On the other hand, if supporting multiple methods at once makes sense
> (say librados adds a 'cephy' method, and that users could legitimately
> use both 'cephx;cephy' and 'cephy;cephx' with different behaviors), then
> keeping auth as an array of instances of a simple flat union scales
> nicer than having to add a combinatorial explosion of branches to the
> flat union to cover every useful combination of auth_supported methods.
> Maybe I'm overthinking it.
> 

I spoke over email with Jason Dillaman (cc'ed), and this is what he told me
with regards to the authentication methods, and what cephx;none means:

On Thu, Mar 23, 2017 at 06:04:30PM -0400, Jason Dillaman wrote:
> It's saying that the client is willing to connect to a server that
> uses cephx auth or a server that uses no auth. Looking at the code,
> the "auth_supported" configuration key is actually deprecated and
> "auth_client_required" should be used instead (which defaults to
> 'cephx, none' already). Since it's been deprecated since v0.55 and if
> you are cleaning things up, feel free to switch to the new one if
> possible.

So from what Jason is saying, it seems like the conclusion we reached over
IRC is correct: it will attempt cephx but also fallback to no auth.

Also, since the preferred auth option may be named different depending on
ceph versions, I know think we probably should not tie the QAPI parameter to
the name of the older deprecated option.

I suggest that the 'auth_supported' parameter for QAPI be renamed to
'auth_method'.  If you don't like the array and the flexibility it provides
at the cost of complexity, I think a flat enum consisting of 3 values like
you mentioned is reasonable.  Since the QAPI does not need to map to the
legacy commandline used by libvirt, I would suggest maybe naming them
slightly different, though: any, none, strict

For 2.9, they could each map to 'auth_supported' like so:
    
    any:     "cephx;none"
    none:    "none"
    strict:  "cephx"

For 2.10, we could try to discover if 'auth_client_required' is supported or
not, and use either it or 'auth_supported' as appropriate (with the same
mappings as above).

The reason I like "any" and "strict", is it gives consistent meanings to
options even if new auth methods are introduced.  For a hypothetical "cephy"
method example:

    any:     "cephy;cephx;none"
    none:    "none"
    strict:  "cephy;cephx"

-Jeff
Markus Armbruster March 24, 2017, 7:05 a.m. UTC | #7
Adding Daniel Berrange for QCryptoSecret expertise.

Jeff Cody <jcody@redhat.com> writes:

> On Thu, Mar 23, 2017 at 04:56:30PM -0500, Eric Blake wrote:
>> On 03/23/2017 04:43 PM, Eric Blake wrote:
>> 
>> > We'd still have to allow libvirt's use of
>> > ":key=...:auth_supported=cephx\\;none" on the command line, but from the
>> > QMP side, we would support exactly one auth method, and libvirt will be
>> > updated to match when it starts targetting blockdev-add instead of
>> > legacy command line.
>> > 
>> > If librados really needs 'cephx;none' any time cephx authorization is
>> > requested, then even though the QMP only requests 'cephx', we can still
>> > map it to 'cephx;none' in qemu - but I'm hoping that setting
>> > auth_supported=cephx rather than auth_supported=cephx;none on the
>> > librados side gives us what we (and libvirt) really want in the first place.
>> 
>> Or, if it becomes something that libvirt wants to allow users to tune in
>> their XML (right now, users don't get a choice, they get either 'none'
>> or 'cephx;none'), a forward-compatible solution under my QMP proposal
>> would be to have qemu add a third enum state, "none", "cephx", and
>> "cephx-no-fallback".
>> 
>> On the other hand, if supporting multiple methods at once makes sense
>> (say librados adds a 'cephy' method, and that users could legitimately
>> use both 'cephx;cephy' and 'cephy;cephx' with different behaviors), then
>> keeping auth as an array of instances of a simple flat union scales
>> nicer than having to add a combinatorial explosion of branches to the
>> flat union to cover every useful combination of auth_supported methods.
>> Maybe I'm overthinking it.
>> 
>
> I spoke over email with Jason Dillaman (cc'ed), and this is what he told me
> with regards to the authentication methods, and what cephx;none means:
>
> On Thu, Mar 23, 2017 at 06:04:30PM -0400, Jason Dillaman wrote:
>> It's saying that the client is willing to connect to a server that
>> uses cephx auth or a server that uses no auth. Looking at the code,
>> the "auth_supported" configuration key is actually deprecated and
>> "auth_client_required" should be used instead (which defaults to
>> 'cephx, none' already). Since it's been deprecated since v0.55 and if
>> you are cleaning things up, feel free to switch to the new one if
>> possible.
>
> So from what Jason is saying, it seems like the conclusion we reached over
> IRC is correct: it will attempt cephx but also fallback to no auth.

So the client offers the server a list of authentication methods with
credentials, and the server picks one it likes.  Makes sense to me.

Inluding "none" in the default less so, but that's of no concern to the
QMP interface, so let's ignore it for now.

> Also, since the preferred auth option may be named different depending on
> ceph versions, I know think we probably should not tie the QAPI parameter to
> the name of the older deprecated option.

Yes.

> I suggest that the 'auth_supported' parameter for QAPI be renamed to
> 'auth_method'.  If you don't like the array and the flexibility it provides
> at the cost of complexity, I think a flat enum consisting of 3 values like
> you mentioned is reasonable.  Since the QAPI does not need to map to the
> legacy commandline used by libvirt, I would suggest maybe naming them
> slightly different, though: any, none, strict
>
> For 2.9, they could each map to 'auth_supported' like so:
>     
>     any:     "cephx;none"
>     none:    "none"
>     strict:  "cephx"
>
> For 2.10, we could try to discover if 'auth_client_required' is supported or
> not, and use either it or 'auth_supported' as appropriate (with the same
> mappings as above).
>
> The reason I like "any" and "strict", is it gives consistent meanings to
> options even if new auth methods are introduced.  For a hypothetical "cephy"
> method example:
>
>     any:     "cephy;cephx;none"
>     none:    "none"
>     strict:  "cephy;cephx"

Two years later, an unfixable cryptograhic weakness in cephx is
discovered.  Some users really, really want to select only "cephy", but
they can't.  We react by pushing out a QEMU update adding method
"stricter", which expands into "cephy".  Libvirt then reacts and pushes
out an update.  And so forth, up the stack.  Many moons later, users can
actually select "cephy".  Thanks, but no thanks.

I think we should expose the current, recommended way to configure
authentication, in a form that is suitable for QAPI/QMP, i.e. structured
data as JSON objects, not strings you need to parse.

If a future authentication method might need something else than a
QCryptoSecret object, we need to take Eric's proposal and make this an
array of unions, where the union tag is the method, and the variant
members supply whatever data the method needs (none: nothing, cephx: a
QCryptoSecret).  Member @password-secret goes away.

Else, we can make it an array of methods, and keep member
@password-secret.

We need to decide quickly to keep rbd fully supported in 2.9.
Jeff Cody March 24, 2017, 12:42 p.m. UTC | #8
On Fri, Mar 24, 2017 at 08:05:49AM +0100, Markus Armbruster wrote:
> Adding Daniel Berrange for QCryptoSecret expertise.
> 
> Jeff Cody <jcody@redhat.com> writes:
> 
> > On Thu, Mar 23, 2017 at 04:56:30PM -0500, Eric Blake wrote:
> >> On 03/23/2017 04:43 PM, Eric Blake wrote:
> >> 
> >> > We'd still have to allow libvirt's use of
> >> > ":key=...:auth_supported=cephx\\;none" on the command line, but from the
> >> > QMP side, we would support exactly one auth method, and libvirt will be
> >> > updated to match when it starts targetting blockdev-add instead of
> >> > legacy command line.
> >> > 
> >> > If librados really needs 'cephx;none' any time cephx authorization is
> >> > requested, then even though the QMP only requests 'cephx', we can still
> >> > map it to 'cephx;none' in qemu - but I'm hoping that setting
> >> > auth_supported=cephx rather than auth_supported=cephx;none on the
> >> > librados side gives us what we (and libvirt) really want in the first place.
> >> 
> >> Or, if it becomes something that libvirt wants to allow users to tune in
> >> their XML (right now, users don't get a choice, they get either 'none'
> >> or 'cephx;none'), a forward-compatible solution under my QMP proposal
> >> would be to have qemu add a third enum state, "none", "cephx", and
> >> "cephx-no-fallback".
> >> 
> >> On the other hand, if supporting multiple methods at once makes sense
> >> (say librados adds a 'cephy' method, and that users could legitimately
> >> use both 'cephx;cephy' and 'cephy;cephx' with different behaviors), then
> >> keeping auth as an array of instances of a simple flat union scales
> >> nicer than having to add a combinatorial explosion of branches to the
> >> flat union to cover every useful combination of auth_supported methods.
> >> Maybe I'm overthinking it.
> >> 
> >
> > I spoke over email with Jason Dillaman (cc'ed), and this is what he told me
> > with regards to the authentication methods, and what cephx;none means:
> >
> > On Thu, Mar 23, 2017 at 06:04:30PM -0400, Jason Dillaman wrote:
> >> It's saying that the client is willing to connect to a server that
> >> uses cephx auth or a server that uses no auth. Looking at the code,
> >> the "auth_supported" configuration key is actually deprecated and
> >> "auth_client_required" should be used instead (which defaults to
> >> 'cephx, none' already). Since it's been deprecated since v0.55 and if
> >> you are cleaning things up, feel free to switch to the new one if
> >> possible.
> >
> > So from what Jason is saying, it seems like the conclusion we reached over
> > IRC is correct: it will attempt cephx but also fallback to no auth.
> 
> So the client offers the server a list of authentication methods with
> credentials, and the server picks one it likes.  Makes sense to me.
> 
> Inluding "none" in the default less so, but that's of no concern to the
> QMP interface, so let's ignore it for now.
> 
> > Also, since the preferred auth option may be named different depending on
> > ceph versions, I know think we probably should not tie the QAPI parameter to
> > the name of the older deprecated option.
> 
> Yes.
> 
> > I suggest that the 'auth_supported' parameter for QAPI be renamed to
> > 'auth_method'.  If you don't like the array and the flexibility it provides
> > at the cost of complexity, I think a flat enum consisting of 3 values like
> > you mentioned is reasonable.  Since the QAPI does not need to map to the
> > legacy commandline used by libvirt, I would suggest maybe naming them
> > slightly different, though: any, none, strict
> >
> > For 2.9, they could each map to 'auth_supported' like so:
> >     
> >     any:     "cephx;none"
> >     none:    "none"
> >     strict:  "cephx"
> >
> > For 2.10, we could try to discover if 'auth_client_required' is supported or
> > not, and use either it or 'auth_supported' as appropriate (with the same
> > mappings as above).
> >
> > The reason I like "any" and "strict", is it gives consistent meanings to
> > options even if new auth methods are introduced.  For a hypothetical "cephy"
> > method example:
> >
> >     any:     "cephy;cephx;none"
> >     none:    "none"
> >     strict:  "cephy;cephx"
> 
> Two years later, an unfixable cryptograhic weakness in cephx is
> discovered.  Some users really, really want to select only "cephy", but
> they can't.  We react by pushing out a QEMU update adding method
> "stricter", which expands into "cephy".  Libvirt then reacts and pushes
> out an update.  And so forth, up the stack.  Many moons later, users can
> actually select "cephy".  Thanks, but no thanks.
> 

Good point; it could be dealt with, but only clumsily.


> I think we should expose the current, recommended way to configure
> authentication, in a form that is suitable for QAPI/QMP, i.e. structured
> data as JSON objects, not strings you need to parse.
> 
> If a future authentication method might need something else than a
> QCryptoSecret object, we need to take Eric's proposal and make this an
> array of unions, where the union tag is the method, and the variant
> members supply whatever data the method needs (none: nothing, cephx: a
> QCryptoSecret).  Member @password-secret goes away.
> 

I guess it is always technically a possibility that a new method would need
something different.  Different methods may of course change the assumptions
about the requirement of a 'user' or not, etc.., as well.

> Else, we can make it an array of methods, and keep member
> @password-secret.
> 

Do you mean keep it as it currently is (just renamed)?

One new bit we should add in, if we stay with this method, is to throw an
error if user/password-secret is provided but only "none" is selected as the
auth method.

The current method essentially pushes the decision of the correct
combination of methods to use to libvirt, which feels like the right place
to be making that decision anyway.


> We need to decide quickly to keep rbd fully supported in 2.9.

Agree.  My preference is to leave it as an array of methods, so long as that
is tenable to libvirt.


-Jeff
Eric Blake March 24, 2017, 1:49 p.m. UTC | #9
On 03/24/2017 07:42 AM, Jeff Cody wrote:

> Agree.  My preference is to leave it as an array of methods, so long as that
> is tenable to libvirt.

The -drive syntax should remain unchanged (that's an absolute must for
libvirt).  But the QMP syntax being an array of methods sounds best to
me, and I think password-secret should be part of the array.  So my vote
would be for:

{ "driver": "rbd", "image": "foo",
  "auth": [ { "type": "cephx", "password-secret": "sec0" },
            { "type": "none" } ],
  "pool": "bar" }

It makes mapping -drive arguments into QMP form a bit trickier, but the
QMP form is then easily extensible if we add another auth method down
the road.
Jeff Cody March 24, 2017, 2:10 p.m. UTC | #10
On Fri, Mar 24, 2017 at 08:49:20AM -0500, Eric Blake wrote:
> On 03/24/2017 07:42 AM, Jeff Cody wrote:
> 
> > Agree.  My preference is to leave it as an array of methods, so long as that
> > is tenable to libvirt.
> 
> The -drive syntax should remain unchanged (that's an absolute must for
> libvirt).  But the QMP syntax being an array of methods sounds best to
> me, and I think password-secret should be part of the array.  So my vote
> would be for:
> 
> { "driver": "rbd", "image": "foo",
>   "auth": [ { "type": "cephx", "password-secret": "sec0" },
>             { "type": "none" } ],
>   "pool": "bar" }
> 
> It makes mapping -drive arguments into QMP form a bit trickier, but the
> QMP form is then easily extensible if we add another auth method down
> the road.
> 

In that case, what about adding user as well, and not just password-secret?

Jeff
Eric Blake March 24, 2017, 2:31 p.m. UTC | #11
On 03/24/2017 09:10 AM, Jeff Cody wrote:
> On Fri, Mar 24, 2017 at 08:49:20AM -0500, Eric Blake wrote:
>> On 03/24/2017 07:42 AM, Jeff Cody wrote:
>>
>>> Agree.  My preference is to leave it as an array of methods, so long as that
>>> is tenable to libvirt.
>>
>> The -drive syntax should remain unchanged (that's an absolute must for
>> libvirt).  But the QMP syntax being an array of methods sounds best to
>> me, and I think password-secret should be part of the array.  So my vote
>> would be for:
>>
>> { "driver": "rbd", "image": "foo",
>>   "auth": [ { "type": "cephx", "password-secret": "sec0" },
>>             { "type": "none" } ],
>>   "pool": "bar" }
>>
>> It makes mapping -drive arguments into QMP form a bit trickier, but the
>> QMP form is then easily extensible if we add another auth method down
>> the road.
>>
> 
> In that case, what about adding user as well, and not just password-secret?

Makes sense - anything that is associated solely with cephx should
belong to the same flat-union branch for cephx, rather than at the top
level.
Kevin Wolf March 24, 2017, 5:54 p.m. UTC | #12
Am 24.03.2017 um 14:49 hat Eric Blake geschrieben:
> On 03/24/2017 07:42 AM, Jeff Cody wrote:
> 
> > Agree.  My preference is to leave it as an array of methods, so long as that
> > is tenable to libvirt.
> 
> The -drive syntax should remain unchanged (that's an absolute must for
> libvirt).  But the QMP syntax being an array of methods sounds best to
> me, and I think password-secret should be part of the array.  So my vote
> would be for:
> 
> { "driver": "rbd", "image": "foo",
>   "auth": [ { "type": "cephx", "password-secret": "sec0" },
>             { "type": "none" } ],
>   "pool": "bar" }
> 
> It makes mapping -drive arguments into QMP form a bit trickier, but the
> QMP form is then easily extensible if we add another auth method down
> the road.

Not sure if anybody cares, but I came to the same conclusion, so I like
this.

Kevin
Markus Armbruster March 27, 2017, 5:58 a.m. UTC | #13
Eric Blake <eblake@redhat.com> writes:

> On 03/24/2017 09:10 AM, Jeff Cody wrote:
>> On Fri, Mar 24, 2017 at 08:49:20AM -0500, Eric Blake wrote:
>>> On 03/24/2017 07:42 AM, Jeff Cody wrote:
>>>
>>>> Agree.  My preference is to leave it as an array of methods, so long as that
>>>> is tenable to libvirt.
>>>
>>> The -drive syntax should remain unchanged (that's an absolute must for
>>> libvirt).  But the QMP syntax being an array of methods sounds best to
>>> me, and I think password-secret should be part of the array.  So my vote
>>> would be for:
>>>
>>> { "driver": "rbd", "image": "foo",
>>>   "auth": [ { "type": "cephx", "password-secret": "sec0" },
>>>             { "type": "none" } ],
>>>   "pool": "bar" }
>>>
>>> It makes mapping -drive arguments into QMP form a bit trickier, but the
>>> QMP form is then easily extensible if we add another auth method down
>>> the road.
>>>
>> 
>> In that case, what about adding user as well, and not just password-secret?
>
> Makes sense - anything that is associated solely with cephx should
> belong to the same flat-union branch for cephx, rather than at the top
> level.

I've thought about this some more and have come to the conclusion that
this design is clumsy and overly complex.  Moreover, I suspect our
testing has been poor.  Let me explain.

= Overview =

What we're trying to configure is authentication methods the client is
to offer to the server.

This is not a list, it's a set: the order doesn't matter, and multiple
entries of the same type make no sense.  We could reject multiple
entries, or let the last one win silently, but this is just unnecessary
complexity.

Type "cephx" uses a user name and a key.

Type "none" uses neither (it could theoretically use the user name, but
I've been assured it doesn't).

The user name defaults to "admin".

The key defaults to the user name's entry in a keyring.  There is a
configurable list of key ring files, with a default.  The default
commonly includes /etc/ceph/client.keyring.

= Librados configuration =

Librados takes these configuration bits as follows:

* The user name is to be passed to rados_create().  NULL means default
  to "admin".

* The key may be passed to rados_conf_set() with key "key" (value is the
  key) or "keyfile" (value is name of the file containing the key).
  Documentation discourages use of "key".

* The list of keyrings may passed to rados_conf_set() with key
  "keyring" and a value listing file names separated by ','.  At least
  according to the documentation; the source looks like any non-empty
  sequence of [;,= \t]* serves as separator.

* The offered authentication methods may be passed to rados_conf_set()
  with key "auth_supported" (deprecated) or "auth_client_required", and
  a value listing methods separated by "," (or maybe [;,= \t]*, see
  above).  The methods are "cephx" and "none".  Default is "cephx,none".

= Command line -drive =

With -drive file=rbd:pool/image[@snapshot][:key=value...], the
key=value... part lets you specify arbitrary rados_conf_set() settings,
except pseudo-key "id" is mapped to the user name instead, and
pseudo-key "conf" names a rados configuration file.  This overloading of
rados_conf_set() keys and our own pseudo-keys isn't pretty, but it's a
done deal.  The full set of authentication configuration discussed above
is available as keys "id", "key", "keyfile", "keyring", "auth_supported"
and "auth_client_required".  Also via "conf", of course.

These -drive rbd:...:key=value settings are also available in -drive
QemuOpts syntax -drive driver=rbd,key=value:

* Pseudo-key "id" is "user" in QemuOpts.

* Pseudo-key "conf" is "conf" in QemuOpts, too

* Any other keys together become "keyvalue-pairs" in QemuOpts, with
  the same key=value:... syntax.

Additionally, QemuOpts-only "password-secret" lets you set
rados_conf_set() key "key" to a value obtained from the QCryptoSecret
interface.

Note that @password-secret is a misnomer: this is *not* a password, it's
a *key*.  Calling it a password is confusing, and makes it harder to
mentally connect QMP and Ceph configuration.

The settings in file=rbd:... override the ones in QemuOpts (that's how
->bdrv_parse_filename() works), which in turn override (I think)
settings from a config file.  Note that *any* key other than "id" and
"conf" in file=rbd:... completely overrides *all* keys in
"keyvalue-pairs".

Except "password-secret" works the other way: it overrides "key" set in
file=rbd:... or "keyvalue-pairs".

As so often with syntactic sugar, once you actually explain how it
works, you realize what a bloody mess it is.

It's not quite clear whether "keyvalue-pairs" is really meant for the
user, or just for internal use to implement file=rbd:...  I posted a
patch to hide it from the user.

= QMP blockdev-add and command line -blockdev =

The current QAPI/QMP schema lets you specify only a few settings
directly: pseudo-keys "id" and "conf" (optional members @user and
@conf), keys "key" and "auth_supported" (optional members
@password-secret and @auth_supported).  The only way to specify other
rados_conf_set() settings such as "keyfile" and "keyring" is via "conf".

Begs the question how the settings you can specify directly interact
with the config file.  I figure they override the config file.

Let's review how this could be used.

If you specify no optional members, you get the Ceph defaults described
above.  Good.

If you want to override the default user, there's @user.  Good.

If you want to override the keyring, you have to fall back to @conf.
Not ideal, but good enough for 2.9.  I guess most users will be fine
with the default keyrings.

If you want to override the authentication methods, you have several
options:

* Use @conf and set auth_supported (deprecated) or auth_client_required
  in the config file

* Use @auth_supported like this:

      "auth_supported": [ { "auth": METHOD}, ... ]

  Clumsy.

If you want to override the key, you again have several options:

* Use @conf and set keyfile or key in the config file

* Use @password-secret to get it from the QCryptoSecret interface

  Did we actually test this?

= What to do for 2.9 =

I propose to

* drop both "auth_supported" and "password-secret" from the QAPI schema

* drop "password-secret" from QemuOpts

* hide "keyvalue-pairs" in QemuOpts

No existing usage is affected, since all these things are new in 2.9.

Users who need something else than the default keyring can continue to
configure alternate keys and keyrings with -drive, both directly with
file=rbd:...:key=value and with a config file.  With -blockdev /
blockdev_add, they need to use the config file.

We can consider improvements post 2.9.
Jeff Cody March 27, 2017, 4:41 p.m. UTC | #14
On Mon, Mar 27, 2017 at 07:58:51AM +0200, Markus Armbruster wrote:
> Eric Blake <eblake@redhat.com> writes:
> 
> > On 03/24/2017 09:10 AM, Jeff Cody wrote:
> >> On Fri, Mar 24, 2017 at 08:49:20AM -0500, Eric Blake wrote:
> >>> On 03/24/2017 07:42 AM, Jeff Cody wrote:
> >>>
> >>>> Agree.  My preference is to leave it as an array of methods, so long as that
> >>>> is tenable to libvirt.
> >>>
> >>> The -drive syntax should remain unchanged (that's an absolute must for
> >>> libvirt).  But the QMP syntax being an array of methods sounds best to
> >>> me, and I think password-secret should be part of the array.  So my vote
> >>> would be for:
> >>>
> >>> { "driver": "rbd", "image": "foo",
> >>>   "auth": [ { "type": "cephx", "password-secret": "sec0" },
> >>>             { "type": "none" } ],
> >>>   "pool": "bar" }
> >>>
> >>> It makes mapping -drive arguments into QMP form a bit trickier, but the
> >>> QMP form is then easily extensible if we add another auth method down
> >>> the road.
> >>>
> >> 
> >> In that case, what about adding user as well, and not just password-secret?
> >
> > Makes sense - anything that is associated solely with cephx should
> > belong to the same flat-union branch for cephx, rather than at the top
> > level.
> 
> I've thought about this some more and have come to the conclusion that
> this design is clumsy and overly complex.  Moreover, I suspect our
> testing has been poor.  Let me explain.
> 
> = Overview =
> 
> What we're trying to configure is authentication methods the client is
> to offer to the server.
> 
> This is not a list, it's a set: the order doesn't matter, and multiple
> entries of the same type make no sense.  We could reject multiple
> entries, or let the last one win silently, but this is just unnecessary
> complexity.
> 
> Type "cephx" uses a user name and a key.
> 
> Type "none" uses neither (it could theoretically use the user name, but
> I've been assured it doesn't).
> 
> The user name defaults to "admin".
> 
> The key defaults to the user name's entry in a keyring.  There is a
> configurable list of key ring files, with a default.  The default
> commonly includes /etc/ceph/client.keyring.
> 

I don't think 'client.keyring' is one of the defaults.  I know
/etc/ceph/keyring is, however.


> = Librados configuration =
> 
> Librados takes these configuration bits as follows:
> 
> * The user name is to be passed to rados_create().  NULL means default
>   to "admin".
> 
> * The key may be passed to rados_conf_set() with key "key" (value is the
>   key) or "keyfile" (value is name of the file containing the key).
>   Documentation discourages use of "key".
> 
> * The list of keyrings may passed to rados_conf_set() with key
>   "keyring" and a value listing file names separated by ','.  At least
>   according to the documentation; the source looks like any non-empty
>   sequence of [;,= \t]* serves as separator.
> 
> * The offered authentication methods may be passed to rados_conf_set()
>   with key "auth_supported" (deprecated) or "auth_client_required", and
>   a value listing methods separated by "," (or maybe [;,= \t]*, see
>   above).  The methods are "cephx" and "none".  Default is "cephx,none".
> 
> = Command line -drive =
> 
> With -drive file=rbd:pool/image[@snapshot][:key=value...], the
> key=value... part lets you specify arbitrary rados_conf_set() settings,
> except pseudo-key "id" is mapped to the user name instead, and
> pseudo-key "conf" names a rados configuration file.  This overloading of
> rados_conf_set() keys and our own pseudo-keys isn't pretty, but it's a
> done deal.  The full set of authentication configuration discussed above
> is available as keys "id", "key", "keyfile", "keyring", "auth_supported"
> and "auth_client_required".  Also via "conf", of course.
> 
> These -drive rbd:...:key=value settings are also available in -drive
> QemuOpts syntax -drive driver=rbd,key=value:
> 
> * Pseudo-key "id" is "user" in QemuOpts.
> 
> * Pseudo-key "conf" is "conf" in QemuOpts, too
> 
> * Any other keys together become "keyvalue-pairs" in QemuOpts, with
>   the same key=value:... syntax.
> 
> Additionally, QemuOpts-only "password-secret" lets you set
> rados_conf_set() key "key" to a value obtained from the QCryptoSecret
> interface.
> 
> Note that @password-secret is a misnomer: this is *not* a password, it's
> a *key*.  Calling it a password is confusing, and makes it harder to
> mentally connect QMP and Ceph configuration.
> 

Good point; @key-secret would be a better name


> The settings in file=rbd:... override the ones in QemuOpts (that's how
> ->bdrv_parse_filename() works), which in turn override (I think)
> settings from a config file.  Note that *any* key other than "id" and
> "conf" in file=rbd:... completely overrides *all* keys in
> "keyvalue-pairs".
> 
> Except "password-secret" works the other way: it overrides "key" set in
> file=rbd:... or "keyvalue-pairs".
> 
> As so often with syntactic sugar, once you actually explain how it
> works, you realize what a bloody mess it is.
> 
> It's not quite clear whether "keyvalue-pairs" is really meant for the
> user, or just for internal use to implement file=rbd:...  I posted a
> patch to hide it from the user.
> 
> = QMP blockdev-add and command line -blockdev =
> 
> The current QAPI/QMP schema lets you specify only a few settings
> directly: pseudo-keys "id" and "conf" (optional members @user and
> @conf), keys "key" and "auth_supported" (optional members
> @password-secret and @auth_supported).  The only way to specify other
> rados_conf_set() settings such as "keyfile" and "keyring" is via "conf".
> 
> Begs the question how the settings you can specify directly interact
> with the config file.  I figure they override the config file.
> 

Yes, looking at the code rados_conf_set() will override both the config
file, and environment variables.


However, certain environment variables will override settings in the
specified "conf" file.  I think "CEPH_KEYRING" is the only one (corresponds
to "keyring"), but I am not sure there are not others.  

This is probably a reason to provide an option for "keyring" via QAPI.

> Let's review how this could be used.
> 
> If you specify no optional members, you get the Ceph defaults described
> above.  Good.
> 
> If you want to override the default user, there's @user.  Good.
> 
> If you want to override the keyring, you have to fall back to @conf.
> Not ideal, but good enough for 2.9.  I guess most users will be fine
> with the default keyrings.
> 

Unless the environment variable CEPH_KEYRING is set, at which point "conf"
won't override it, unless I am missing something.  However, we could either
provide a QAPI interface to set the keyring, or keep a user/key option.


> If you want to override the authentication methods, you have several
> options:
> 
> * Use @conf and set auth_supported (deprecated) or auth_client_required
>   in the config file
> 
> * Use @auth_supported like this:
> 
>       "auth_supported": [ { "auth": METHOD}, ... ]
> 
>   Clumsy.
> 
> If you want to override the key, you again have several options:
> 
> * Use @conf and set keyfile or key in the config file
> 
> * Use @password-secret to get it from the QCryptoSecret interface
> 
>   Did we actually test this?

Yes, and it works.  One caveat: the key obtained from the keyring or
"ceph auth list" are base64 encoded, and qemu_rbd_set_auth() base64 encodes
the key itself into base64.  The rados_conf_set() value for "key" is assumed
to be base64 encoded.  This means the secret file needs to have the key not
base64 encoded, with the current code.


> 
> = What to do for 2.9 =
> 
> I propose to
> 
> * drop both "auth_supported" and "password-secret" from the QAPI schema
> 
> * drop "password-secret" from QemuOpts
> 
> * hide "keyvalue-pairs" in QemuOpts
> 
> No existing usage is affected, since all these things are new in 2.9.
> 
> Users who need something else than the default keyring can continue to
> configure alternate keys and keyrings with -drive, both directly with
> file=rbd:...:key=value and with a config file.  With -blockdev /
> blockdev_add, they need to use the config file.
> 
> We can consider improvements post 2.9.

I am fine with this; the only real functional limitation with dropping this
for 2.9 is that default keyring cannot be overridden in certain scenarios
(it is set via an environment variable, and 'conf' won't override it).


-Jeff
Markus Armbruster March 27, 2017, 6:20 p.m. UTC | #15
Jeff Cody <jcody@redhat.com> writes:

> On Mon, Mar 27, 2017 at 07:58:51AM +0200, Markus Armbruster wrote:
>> Eric Blake <eblake@redhat.com> writes:
>> 
>> > On 03/24/2017 09:10 AM, Jeff Cody wrote:
>> >> On Fri, Mar 24, 2017 at 08:49:20AM -0500, Eric Blake wrote:
>> >>> On 03/24/2017 07:42 AM, Jeff Cody wrote:
>> >>>
>> >>>> Agree.  My preference is to leave it as an array of methods, so long as that
>> >>>> is tenable to libvirt.
>> >>>
>> >>> The -drive syntax should remain unchanged (that's an absolute must for
>> >>> libvirt).  But the QMP syntax being an array of methods sounds best to
>> >>> me, and I think password-secret should be part of the array.  So my vote
>> >>> would be for:
>> >>>
>> >>> { "driver": "rbd", "image": "foo",
>> >>>   "auth": [ { "type": "cephx", "password-secret": "sec0" },
>> >>>             { "type": "none" } ],
>> >>>   "pool": "bar" }
>> >>>
>> >>> It makes mapping -drive arguments into QMP form a bit trickier, but the
>> >>> QMP form is then easily extensible if we add another auth method down
>> >>> the road.
>> >>>
>> >> 
>> >> In that case, what about adding user as well, and not just password-secret?
>> >
>> > Makes sense - anything that is associated solely with cephx should
>> > belong to the same flat-union branch for cephx, rather than at the top
>> > level.
>> 
>> I've thought about this some more and have come to the conclusion that
>> this design is clumsy and overly complex.  Moreover, I suspect our
>> testing has been poor.  Let me explain.
>> 
>> = Overview =
>> 
>> What we're trying to configure is authentication methods the client is
>> to offer to the server.
>> 
>> This is not a list, it's a set: the order doesn't matter, and multiple
>> entries of the same type make no sense.  We could reject multiple
>> entries, or let the last one win silently, but this is just unnecessary
>> complexity.
>> 
>> Type "cephx" uses a user name and a key.
>> 
>> Type "none" uses neither (it could theoretically use the user name, but
>> I've been assured it doesn't).
>> 
>> The user name defaults to "admin".
>> 
>> The key defaults to the user name's entry in a keyring.  There is a
>> configurable list of key ring files, with a default.  The default
>> commonly includes /etc/ceph/client.keyring.
>> 
>
> I don't think 'client.keyring' is one of the defaults.  I know
> /etc/ceph/keyring is, however.

Double-checking...  source suggests the default is actually
/etc/ceph/$cluster.$name.keyring,/etc/ceph/$cluster.keyring,/etc/ceph/keyring,/etc/ceph/keyring.bin

https://github.com/ceph/ceph/blob/master/src/common/config_opts.h#L172

>> = Librados configuration =
>> 
>> Librados takes these configuration bits as follows:
>> 
>> * The user name is to be passed to rados_create().  NULL means default
>>   to "admin".
>> 
>> * The key may be passed to rados_conf_set() with key "key" (value is the
>>   key) or "keyfile" (value is name of the file containing the key).
>>   Documentation discourages use of "key".
>> 
>> * The list of keyrings may passed to rados_conf_set() with key
>>   "keyring" and a value listing file names separated by ','.  At least
>>   according to the documentation; the source looks like any non-empty
>>   sequence of [;,= \t]* serves as separator.
>> 
>> * The offered authentication methods may be passed to rados_conf_set()
>>   with key "auth_supported" (deprecated) or "auth_client_required", and
>>   a value listing methods separated by "," (or maybe [;,= \t]*, see
>>   above).  The methods are "cephx" and "none".  Default is "cephx,none".
>> 
>> = Command line -drive =
>> 
>> With -drive file=rbd:pool/image[@snapshot][:key=value...], the
>> key=value... part lets you specify arbitrary rados_conf_set() settings,
>> except pseudo-key "id" is mapped to the user name instead, and
>> pseudo-key "conf" names a rados configuration file.  This overloading of
>> rados_conf_set() keys and our own pseudo-keys isn't pretty, but it's a
>> done deal.  The full set of authentication configuration discussed above
>> is available as keys "id", "key", "keyfile", "keyring", "auth_supported"
>> and "auth_client_required".  Also via "conf", of course.
>> 
>> These -drive rbd:...:key=value settings are also available in -drive
>> QemuOpts syntax -drive driver=rbd,key=value:
>> 
>> * Pseudo-key "id" is "user" in QemuOpts.
>> 
>> * Pseudo-key "conf" is "conf" in QemuOpts, too
>> 
>> * Any other keys together become "keyvalue-pairs" in QemuOpts, with
>>   the same key=value:... syntax.
>> 
>> Additionally, QemuOpts-only "password-secret" lets you set
>> rados_conf_set() key "key" to a value obtained from the QCryptoSecret
>> interface.
>> 
>> Note that @password-secret is a misnomer: this is *not* a password, it's
>> a *key*.  Calling it a password is confusing, and makes it harder to
>> mentally connect QMP and Ceph configuration.
>> 
>
> Good point; @key-secret would be a better name
>
>
>> The settings in file=rbd:... override the ones in QemuOpts (that's how
>> ->bdrv_parse_filename() works), which in turn override (I think)
>> settings from a config file.  Note that *any* key other than "id" and
>> "conf" in file=rbd:... completely overrides *all* keys in
>> "keyvalue-pairs".
>> 
>> Except "password-secret" works the other way: it overrides "key" set in
>> file=rbd:... or "keyvalue-pairs".
>> 
>> As so often with syntactic sugar, once you actually explain how it
>> works, you realize what a bloody mess it is.
>> 
>> It's not quite clear whether "keyvalue-pairs" is really meant for the
>> user, or just for internal use to implement file=rbd:...  I posted a
>> patch to hide it from the user.
>> 
>> = QMP blockdev-add and command line -blockdev =
>> 
>> The current QAPI/QMP schema lets you specify only a few settings
>> directly: pseudo-keys "id" and "conf" (optional members @user and
>> @conf), keys "key" and "auth_supported" (optional members
>> @password-secret and @auth_supported).  The only way to specify other
>> rados_conf_set() settings such as "keyfile" and "keyring" is via "conf".
>> 
>> Begs the question how the settings you can specify directly interact
>> with the config file.  I figure they override the config file.
>> 
>
> Yes, looking at the code rados_conf_set() will override both the config
> file, and environment variables.
>
>
> However, certain environment variables will override settings in the
> specified "conf" file.  I think "CEPH_KEYRING" is the only one (corresponds
> to "keyring"), but I am not sure there are not others.  
>
> This is probably a reason to provide an option for "keyring" via QAPI.

I'm open to provide more configuration knobs via QAPI, but for 2.9, I
propose to stick to the smallest interface that can possibly work.

>> Let's review how this could be used.
>> 
>> If you specify no optional members, you get the Ceph defaults described
>> above.  Good.
>> 
>> If you want to override the default user, there's @user.  Good.
>> 
>> If you want to override the keyring, you have to fall back to @conf.
>> Not ideal, but good enough for 2.9.  I guess most users will be fine
>> with the default keyrings.
>> 
>
> Unless the environment variable CEPH_KEYRING is set, at which point "conf"
> won't override it, unless I am missing something.  However, we could either
> provide a QAPI interface to set the keyring, or keep a user/key option.

For 2.9 QAPI/QMP, I'd say our story for authentication should be "stick
to *Ceph* configuration; how you use it is up to you".  I.e. set up
suitable keyrings, and how exactly you tell Ceph to use non-default
keyrings (config file, environment variable, whatever) is your problem.

>> If you want to override the authentication methods, you have several
>> options:
>> 
>> * Use @conf and set auth_supported (deprecated) or auth_client_required
>>   in the config file
>> 
>> * Use @auth_supported like this:
>> 
>>       "auth_supported": [ { "auth": METHOD}, ... ]
>> 
>>   Clumsy.
>> 
>> If you want to override the key, you again have several options:
>> 
>> * Use @conf and set keyfile or key in the config file
>> 
>> * Use @password-secret to get it from the QCryptoSecret interface
>> 
>>   Did we actually test this?
>
> Yes, and it works.  One caveat: the key obtained from the keyring or
> "ceph auth list" are base64 encoded, and qemu_rbd_set_auth() base64 encodes
> the key itself into base64.  The rados_conf_set() value for "key" is assumed
> to be base64 encoded.  This means the secret file needs to have the key not
> base64 encoded, with the current code.

Good to know, thanks.  Documentation or at least comments explaining
this would be welcome.

>> = What to do for 2.9 =
>> 
>> I propose to
>> 
>> * drop both "auth_supported" and "password-secret" from the QAPI schema
>> 
>> * drop "password-secret" from QemuOpts
>> 
>> * hide "keyvalue-pairs" in QemuOpts
>> 
>> No existing usage is affected, since all these things are new in 2.9.
>> 
>> Users who need something else than the default keyring can continue to
>> configure alternate keys and keyrings with -drive, both directly with
>> file=rbd:...:key=value and with a config file.  With -blockdev /
>> blockdev_add, they need to use the config file.
>> 
>> We can consider improvements post 2.9.
>
> I am fine with this; the only real functional limitation with dropping this
> for 2.9 is that default keyring cannot be overridden in certain scenarios
> (it is set via an environment variable, and 'conf' won't override it).

My PATCH RFC v3 implements this, let's get it reviewed and merged.

Regarding the limitation: if you pass an environment variable to QEMU,
then realize it gets in your way, consider not passing it :)
Daniel P. Berrangé April 3, 2017, 11:25 a.m. UTC | #16
On Mon, Mar 27, 2017 at 07:58:51AM +0200, Markus Armbruster wrote:
> = What to do for 2.9 =
> 
> I propose to
> 
> * drop both "auth_supported" and "password-secret" from the QAPI schema
> 
> * drop "password-secret" from QemuOpts
> 
> * hide "keyvalue-pairs" in QemuOpts
> 
> No existing usage is affected, since all these things are new in 2.9.

Maybe I'm mis-understanding what you're suggesting wrt QemuOpts, but
'password-secret' with RBD is not new in 2.9.0

It was added in 2.6.0 in this commit:

commit 60390a2192e7b38aee18db6ce7fb740498709737
Author: Daniel P. Berrange <berrange@redhat.com>
Date:   Thu Jan 21 14:19:19 2016 +0000

    rbd: add support for getting password from QCryptoSecret object
    
    Currently RBD passwords must be provided on the command line
    via
    
      $QEMU -drive file=rbd:pool/image:id=myname:\
                   key=QVFDVm41aE82SHpGQWhBQXEwTkN2OGp0SmNJY0UrSE9CbE1RMUE=:\
                   auth_supported=cephx
    
    This is insecure because the key is visible in the OS process
    listing.
    
    This adds support for an 'password-secret' parameter in the RBD
    parameters that can be used with the QCryptoSecret object to
    provide the password via a file:
    
      echo "QVFDVm41aE82SHpGQWhBQXEwTkN2OGp0SmNJY0UrSE9CbE1RMUE=" > poolkey.b64
      $QEMU -object secret,id=secret0,file=poolkey.b64,format=base64 \
            -drive driver=rbd,filename=rbd:pool/image:id=myname:\
                   auth_supported=cephx,password-secret=secret0
    
    Reviewed-by: Josh Durgin <jdurgin@redhat.com>
    Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
    Message-id: 1453385961-10718-2-git-send-email-berrange@redhat.com
    Signed-off-by: Jeff Cody <jcody@redhat.com>

Regards,
Daniel
Eric Blake April 3, 2017, 7:03 p.m. UTC | #17
On 04/03/2017 06:25 AM, Daniel P. Berrange wrote:
> On Mon, Mar 27, 2017 at 07:58:51AM +0200, Markus Armbruster wrote:
>> = What to do for 2.9 =
>>
>> I propose to
>>
>> * drop both "auth_supported" and "password-secret" from the QAPI schema
>>
>> * drop "password-secret" from QemuOpts
>>
>> * hide "keyvalue-pairs" in QemuOpts
>>
>> No existing usage is affected, since all these things are new in 2.9.
> 
> Maybe I'm mis-understanding what you're suggesting wrt QemuOpts, but
> 'password-secret' with RBD is not new in 2.9.0

We updated things in the respin of this series; the actual committed
version (ending in commit d1c13688) did NOT kill password-secret from
QemuOpts, but merely removed it from QMP (it was the QMP portion that
was attempted to be new in 2.9).
diff mbox

Patch

diff --git a/block/rbd.c b/block/rbd.c
index 8ba0f79..f460d71 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -566,7 +566,7 @@  static char *rbd_auth(QDict *options)
     int i;
 
     for (i = 0;; i++) {
-        sprintf(keybuf, "auth-supported.%d.auth", i);
+        sprintf(keybuf, "auth-supported.%d", i);
         val = qdict_get(options, keybuf);
         if (!val) {
             break;
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 0f132fc..fe1e40f 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2601,25 +2601,14 @@ 
 
 
 ##
-# @RbdAuthSupport:
-#
-# An enumeration of RBD auth support
-#
-# Since: 2.9
-##
-{ 'enum': 'RbdAuthSupport',
-  'data': [ 'cephx', 'none' ] }
-
-
-##
 # @RbdAuthMethod:
 #
 # An enumeration of rados auth_supported types
 #
 # Since: 2.9
 ##
-{ 'struct': 'RbdAuthMethod',
-  'data': { 'auth': 'RbdAuthSupport' } }
+{ 'enum': 'RbdAuthMethod',
+  'data': [ 'cephx', 'none' ] }
 
 ##
 # @BlockdevOptionsRbd: