[pve-devel] [PATCH common] fix #2023: try out all available yubico api endpoints

Thomas Lamprecht t.lamprecht at proxmox.com
Tue Apr 9 09:22:25 CEST 2019


On 4/9/19 9:21 AM, Dominik Csapak wrote:
> one comment inline
> 
> On 4/9/19 9:11 AM, Thomas Lamprecht wrote:
>> While we moved to the new v2 API a bit ago we still only ever tried
>> a single hard coded endpoint, but yubico say:
>>
>>> To ensure high-availability, configure your client to
>>> simultaneously issue requests to all five addresses and accept the
>>> first successful reply.
>> -- yubico server status site [0]
>>
>> For now I ommitted the initial parallel requesting, it's a best
>> effort try, serialized.
>> That could be added on top of this later one, if desired, either by
>> just forking and starting connections in parallel, or some anyevent
>> like async request.
>>
>> But lets hope we can save this complexity completely and wait out
>> until yubico sets up a single highly-available API endpoint. Until
>> then this is a cheap "one can only win" approach.
>>
>> [0]: https://status.yubico.com/2018/11/26/deprecating-yubicloud-v1-protocol-plain-text-requests-and-old-tls-versions/
>>
>> Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
>> ---
>>
>> best (re)viewed with git's ignore all space option (-w) to ignore indentation
>> only changes
>>
>>   src/PVE/OTP.pm | 38 +++++++++++++++++++++++++++++---------
>>   1 file changed, 29 insertions(+), 9 deletions(-)
>>
>> diff --git a/src/PVE/OTP.pm b/src/PVE/OTP.pm
>> index 019076b..f9b6654 100644
>> --- a/src/PVE/OTP.pm
>> +++ b/src/PVE/OTP.pm
>> @@ -46,7 +46,7 @@ sub yubico_compute_param_sig {
>>   }
>>     sub yubico_verify_otp {
>> -    my ($otp, $keys, $url, $api_id, $api_key, $proxy) = @_;
>> +    my ($otp, $keys, $api_url, $api_id, $api_key, $proxy) = @_;
>>         die "yubico: missing password\n" if !defined($otp);
>>       die "yubico: missing API ID\n" if !defined($api_id);
>> @@ -55,7 +55,17 @@ sub yubico_verify_otp {
>>         die "yubico: wrong OTP length\n" if (length($otp) < 32) || (length($otp) > 48);
>>   -    $url = 'https://api2.yubico.com/wsapi/2.0/verify' if !defined($url);
>> +    my $urls;
>> +    if (!defined($api_url)) {
>> +    # see https://status.yubico.com/2018/11/26/deprecating-yubicloud-v1-protocol-plain-text-requests-and-old-tls-versions/
>> +    $urls = [
>> +        map { "https://api${_}.yubico.com/wsapi/2.0/verify" } (''), (2..5)
>> +    ];
>> +    } elsif (!ref($api_url)) {
>> +    $urls = [ $api_url ];
>> +    } else {
>> +    $urls = $api_url;
>> +    }
>>         my $params = {
>>       nonce =>  Digest::SHA::hmac_sha1_hex(time(), rand()),
>> @@ -68,8 +78,6 @@ sub yubico_verify_otp {
>>         $paramstr .= "&h=$sig" if $api_key;
>>   -    my $req = HTTP::Request->new('GET' => "$url?$paramstr");
>> -
>>       my $ua = LWP::UserAgent->new(protocols_allowed => ['http', 'https'], timeout => 30);
>>         if ($proxy) {
>> @@ -78,13 +86,25 @@ sub yubico_verify_otp {
>>       $ua->env_proxy;
>>       }
>>   -    my $response = $ua->request($req);
>> -    my $code = $response->code;
>> +    my ($response, $lasterr);
>> +    for my $url (@$urls) {
>> +    my $req = HTTP::Request->new('GET' => "$url?$paramstr");
>>   -    if ($code != 200) {
>> -    my $msg = $response->message || 'unknown';
>> -    die "Invalid response from server: $code $msg\n";
>> +    $response = $ua->request($req);
>> +    my $code = $response->code;
>> +
>> +    if ($code != 200) {
>> +        $lasterr = $response->message || 'unknown';
>> +        warn "Invalid response from '$url': $code $lasterr\n";
>> +        next;
>> +    } else {
>> +        $lasterr = undef;
> i guess there is a 'last' missing here?
> else we always try all even if we already had a successful attempt ? or am i missing something?

no, you're right, it's missing..

> 
>> +    }
>>       }
>> +    # just report last error to user, don't throw > 5, possible identical, errors
>> +    # at him, they're logged above for an admin already..
>> +    die "Could not connect to any yubico OTP API server specified: $lasterr\n"
>> +    if defined($lasterr);
>>         my $raw = $response->decoded_content;
>>  
> 
> 






More information about the pve-devel mailing list