[pve-devel] [PATCH v3 apiclient] fix #2227: enable totp codes to be passed in cli
Wolfgang Bumiller
w.bumiller at proxmox.com
Mon Aug 19 09:34:12 CEST 2019
On Wed, Aug 14, 2019 at 02:15:40PM +0200, Thomas Lamprecht wrote:
> Am 7/18/19 um 4:44 PM schrieb Oguz Bektas:
> > this patch enables to pass totp codes during cluster join if tfa has been
> > enabled for root at pam (or any other user actually, but root seems to cause the
> > most problems).
> >
> > u2f support is still not implemented.
> >
> > Co-developed-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
> > Co-developed-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
> > Signed-off-by: Oguz Bektas <o.bektas at proxmox.com>
> > ---
> >
> > v2 -> v3:
> > implement thomas' suggestions, namely:
> > * factor out code and handle it outside of the login func
> > * pass $type and $challenge after detecting a two-factor-auth ticket
> > (the detection regex can be improved i think, but i'll leave it like
> > this for now)
> > * also if $type isn't detected, abort after doing a raise
> >
> > PVE/APIClient/LWP.pm | 30 ++++++++++++++++++++++++------
> > 1 file changed, 24 insertions(+), 6 deletions(-)
> >
> > diff --git a/PVE/APIClient/LWP.pm b/PVE/APIClient/LWP.pm
> > index c0e30ff..2cf7ac7 100755
> > --- a/PVE/APIClient/LWP.pm
> > +++ b/PVE/APIClient/LWP.pm
> > @@ -92,6 +92,23 @@ sub update_ticket {
> > $agent->default_header('Cookie', $cookie);
> > }
> >
> > +sub two_factor_auth_login {
> > + my ($self, $type, $challenge) = @_;
> > +
> > + if ($type eq 'PVE:tfa') {
> > + raise("TFA-enabled join currently works only with a TTY.") if !-t STDIN;
>
> This has nothing to do with a PVE node join, it hits us there, yes,
> but that's only the case because we currently only use the apiclient
> there.
> But we may ecxtend it's use in the future, and also other, external
> people and projects may already use it for different cases.
> So please adapt the error message(s) to something more general and
> fitting, i.e., you're doing a login which failed.
>
> > + print "\nEnter OTP code for user $self->{username}: ";
> > + my $tfa_response = <STDIN>;
> > + chomp $tfa_response;
> > + return $self->post('/api2/json/access/tfa', {response => $tfa_response});
> > + } elsif ($type eq 'PVE:u2f') {
> > + # TODO: implement u2f-enabled join
> > + raise("U2F-enabled join is currently not implemented.");
>
> same here
>
> > + } else {
> > + raise("Authentication type not recognized, aborting!");
>
> maybe include the unrecognised type in the error to help us understand
> why someone ran into this, if it happens.
>
> > + }
> > +}
> > +
> > sub login {
> > my ($self) = @_;
> >
> > @@ -129,15 +146,16 @@ sub login {
> > my $res = from_json($response->decoded_content, {utf8 => 1, allow_nonref => 1});
> >
> > my $data = $extract_data->($res);
> > -
> > - # TODO: make it possible to use tfa
> > - if ($data->{ticket} =~ m/^PVE:tfa!/) {
> > - raise("Two Factor Auth is not yet implemented! Try disabling TFA for the user '$username'.\n");
> > - }
> > -
> > $self->update_ticket($data->{ticket});
> > $self->update_csrftoken($data->{CSRFPreventionToken});
> >
> > + # handle two-factor login
> > + if ($data->{ticket} =~ m{^([^\s!]+)![^!]*(!([0-9a-zA-Z/.=_\-+]+))?$}) {
>
> maybe a
>
> my $tfa_ticket_re = qr/^([^\s!]+)![^!]*(!([0-9a-zA-Z/.=_\-+]+))?$/;
While the base64 pattern there is currently only used specifically with u2f
($data =~ /^u2f!...), whereas the 'tfa' case is actually matched as
`$data =~ /^tfa!(.*)$/` in the code currently. (Iow. the number of
"parameters" and restrictions on the content depends on the authentication
type.)
So rather thant restricting the tail, just end with `(?:!(.*))$`, also note
that you are including the '!' character in $2.
> if ($data->{ticket} =~ m/$tfa_ticket_re/) ...
No need to for the m//, jus use =~ $tfa_ticket_re ;-)
More information about the pve-devel
mailing list