DPDK CI discussions
 help / color / mirror / Atom feed
* [PATCH v2] tools: add jwt renewal function to acvp_tool
@ 2023-06-26 21:36 jspewock
  2023-06-27 16:18 ` Aaron Conole
  2023-06-27 16:20 ` Aaron Conole
  0 siblings, 2 replies; 7+ messages in thread
From: jspewock @ 2023-06-26 21:36 UTC (permalink / raw)
  To: aconole; +Cc: ci, Jeremy Spewock

From: Jeremy Spewock <jspewock@iol.unh.edu>

Adds a method that follows the process for renewing your jwt according
to NIST API documentation. This way, if there are load issues and it
takes too long to get vectors back with multi-algorithm testing, the
script will always handle the jwt expiring.

Also added a maximum number of renewals so that the script cannot run
infinitely.

Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu>
---
 tools/acvp/acvp_tool.py | 71 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 63 insertions(+), 8 deletions(-)
 mode change 100755 => 100644 tools/acvp/acvp_tool.py

diff --git a/tools/acvp/acvp_tool.py b/tools/acvp/acvp_tool.py
old mode 100755
new mode 100644
index 40d2f2f..a28760d
--- a/tools/acvp/acvp_tool.py
+++ b/tools/acvp/acvp_tool.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 # SPDX-License-Identifier: BSD-3-Clause
-# Copyright 2022 The University of New Hampshire
+# Copyright 2023 The University of New Hampshire
 
 import hashlib
 import sys
@@ -36,6 +36,8 @@ class ACVPProxy:
         self.totp_path: str = totp_path
         self.login_data: Optional[Dict[str, Any]] = None
         self.session_data: Optional[Dict[str, Any]] = None
+        self.retries: int = 0
+        self.max_retries: int = 2
 
         with open(config_path, 'r') as f:
             self.config: Any = json.load(f)
@@ -70,7 +72,13 @@ class ACVPProxy:
                 cert=self.cert,
                 headers={'Authorization': f'Bearer {token}'}
             )
-            if not response.ok:
+            if response.status_code == 401:
+                if self.__renew_jwt():
+                    token = self.session_data['jwt']
+                    continue
+                logging.error("Failed to renew expired jwt")
+                return None
+            elif not response.ok:
                 logging.error(f'Failed to fetch vector set {url}')
                 logging.error(json.dumps(response.json(), indent=4))
                 return None
@@ -85,6 +93,35 @@ class ACVPProxy:
             logging.info(f'Downloaded vector set {url}')
             return vector_set_json
 
+    def __renew_jwt(self) -> bool:
+        """Renews the jwt in session_data.
+
+        JWTs provided by the NIST API last 30 minutes which can cause this
+        script to fail even with good data. This method renews the jwt using
+        the login endpoint.
+
+        @return: True if successfully renewed token
+        """
+        if self.retries >= self.max_retries:
+            logging.error("Maximum number of jwt renewals has been reached.")
+            return False
+        response = requests.post(
+            url=f'{self.config["url"]}/acvp/v1/login',
+            json=[
+                {'acvVersion': '1.0'},
+                {
+                'password': self.__get_totp(),
+                'accessToken': self.session_data["jwt"]
+                }
+            ],
+            cert=self.cert,
+        )
+        if response.ok:
+            self.retries += 1
+            self.session_data["jwt"] = response.json()[1].pop("accessToken")
+            return True
+        return False
+
     def login(self) -> bool:
         """Log into the API server.
 
@@ -178,6 +215,12 @@ class ACVPProxy:
                         'Authorization': f'Bearer {self.session_data["jwt"]}'
                     }
                 )
+                if result.status_code == 401:
+                    if self.__renew_jwt():
+                        write_data[0]["jwt"] = self.session_data["jwt"]
+                        continue
+                    logging.error("Failed to renew jwt")
+                    return None
                 version, result_json = result.json()
                 if 'retry' in result_json:
                     duration = result_json['retry']
@@ -208,7 +251,19 @@ class ACVPProxy:
                 headers={'Authorization': f'Bearer {self.session_data["jwt"]}'}
             )
 
-            if not response.ok:
+            if response.status_code == 401:
+                if self.__renew_jwt():
+                    response = requests.post(
+                        f'{self.config["url"]}{session_url}/vectorSets/'
+                        f'{vector_set["vsId"]}/results',
+                        json=[version, vector_set],
+                        cert=self.cert,
+                        headers={'Authorization': f'Bearer {self.session_data["jwt"]}'}
+                    )
+                else:
+                    logging.error("Failed to renew jwt")
+                    return False
+            elif not response.ok:
                 has_error = True
                 logging.error(f'Could not upload vector set response for '
                               f'vector set ID {vector_set["vsId"]}.')
@@ -239,13 +294,13 @@ def main(request_path: Optional[str],
         config_path=config_path,
     )
 
-    logging.info('Attempting to log in...')
-    if not proxy.login():
-        logging.error('Could not log in.')
-        sys.exit(1)
-    logging.info('Successfully logged in.')
 
     if request_path:
+        logging.info('Attempting to log in...')
+        if not proxy.login():
+            logging.error('Could not log in.')
+            sys.exit(1)
+        logging.info('Successfully logged in.')
         logging.info('Creating a new test session and downloading vectors...')
         test_session = proxy.register()
         if not test_session:
-- 
2.41.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] tools: add jwt renewal function to acvp_tool
  2023-06-26 21:36 [PATCH v2] tools: add jwt renewal function to acvp_tool jspewock
@ 2023-06-27 16:18 ` Aaron Conole
  2023-06-27 17:31   ` Jeremy Spewock
  2023-06-27 16:20 ` Aaron Conole
  1 sibling, 1 reply; 7+ messages in thread
From: Aaron Conole @ 2023-06-27 16:18 UTC (permalink / raw)
  To: jspewock; +Cc: ci

jspewock@iol.unh.edu writes:

> From: Jeremy Spewock <jspewock@iol.unh.edu>
>
> Adds a method that follows the process for renewing your jwt according
> to NIST API documentation. This way, if there are load issues and it
> takes too long to get vectors back with multi-algorithm testing, the
> script will always handle the jwt expiring.
>
> Also added a maximum number of renewals so that the script cannot run
> infinitely.
>
> Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu>
> ---

Hi Jeremy,

Thanks for the changes, it is much easier to follow now.

I ran this through 'black' and it did flag a few of your changes, but
I don't think it is an issue here because they are single quote
vs. double quote usage, and the usage you have is consistent with the
rest of the file.

>  tools/acvp/acvp_tool.py | 71 ++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 63 insertions(+), 8 deletions(-)
>  mode change 100755 => 100644 tools/acvp/acvp_tool.py

Was this mode change intentional?  I guess it must not be since the
README advocates usage as:

   acvp_tool.py --request $DOWNLOAD_PATH

I can fix on apply if you confirm.

> diff --git a/tools/acvp/acvp_tool.py b/tools/acvp/acvp_tool.py
> old mode 100755
> new mode 100644
> index 40d2f2f..a28760d
> --- a/tools/acvp/acvp_tool.py
> +++ b/tools/acvp/acvp_tool.py
> @@ -1,7 +1,7 @@
>  #!/usr/bin/env python3
>  
>  # SPDX-License-Identifier: BSD-3-Clause
> -# Copyright 2022 The University of New Hampshire
> +# Copyright 2023 The University of New Hampshire
>  
>  import hashlib
>  import sys
> @@ -36,6 +36,8 @@ class ACVPProxy:
>          self.totp_path: str = totp_path
>          self.login_data: Optional[Dict[str, Any]] = None
>          self.session_data: Optional[Dict[str, Any]] = None
> +        self.retries: int = 0
> +        self.max_retries: int = 2
>  
>          with open(config_path, 'r') as f:
>              self.config: Any = json.load(f)
> @@ -70,7 +72,13 @@ class ACVPProxy:
>                  cert=self.cert,
>                  headers={'Authorization': f'Bearer {token}'}
>              )
> -            if not response.ok:
> +            if response.status_code == 401:
> +                if self.__renew_jwt():
> +                    token = self.session_data['jwt']
> +                    continue
> +                logging.error("Failed to renew expired jwt")
> +                return None
> +            elif not response.ok:
>                  logging.error(f'Failed to fetch vector set {url}')
>                  logging.error(json.dumps(response.json(), indent=4))
>                  return None
> @@ -85,6 +93,35 @@ class ACVPProxy:
>              logging.info(f'Downloaded vector set {url}')
>              return vector_set_json
>  
> +    def __renew_jwt(self) -> bool:
> +        """Renews the jwt in session_data.
> +
> +        JWTs provided by the NIST API last 30 minutes which can cause this
> +        script to fail even with good data. This method renews the jwt using
> +        the login endpoint.
> +
> +        @return: True if successfully renewed token
> +        """
> +        if self.retries >= self.max_retries:
> +            logging.error("Maximum number of jwt renewals has been reached.")
> +            return False
> +        response = requests.post(
> +            url=f'{self.config["url"]}/acvp/v1/login',
> +            json=[
> +                {'acvVersion': '1.0'},
> +                {
> +                'password': self.__get_totp(),
> +                'accessToken': self.session_data["jwt"]
> +                }
> +            ],
> +            cert=self.cert,
> +        )
> +        if response.ok:
> +            self.retries += 1
> +            self.session_data["jwt"] = response.json()[1].pop("accessToken")
> +            return True
> +        return False
> +
>      def login(self) -> bool:
>          """Log into the API server.
>  
> @@ -178,6 +215,12 @@ class ACVPProxy:
>                          'Authorization': f'Bearer {self.session_data["jwt"]}'
>                      }
>                  )
> +                if result.status_code == 401:
> +                    if self.__renew_jwt():
> +                        write_data[0]["jwt"] = self.session_data["jwt"]
> +                        continue
> +                    logging.error("Failed to renew jwt")
> +                    return None
>                  version, result_json = result.json()
>                  if 'retry' in result_json:
>                      duration = result_json['retry']
> @@ -208,7 +251,19 @@ class ACVPProxy:
>                  headers={'Authorization': f'Bearer {self.session_data["jwt"]}'}
>              )
>  
> -            if not response.ok:
> +            if response.status_code == 401:
> +                if self.__renew_jwt():
> +                    response = requests.post(
> +                        f'{self.config["url"]}{session_url}/vectorSets/'
> +                        f'{vector_set["vsId"]}/results',
> +                        json=[version, vector_set],
> +                        cert=self.cert,
> +                        headers={'Authorization': f'Bearer {self.session_data["jwt"]}'}
> +                    )
> +                else:
> +                    logging.error("Failed to renew jwt")
> +                    return False
> +            elif not response.ok:
>                  has_error = True
>                  logging.error(f'Could not upload vector set response for '
>                                f'vector set ID {vector_set["vsId"]}.')
> @@ -239,13 +294,13 @@ def main(request_path: Optional[str],
>          config_path=config_path,
>      )
>  
> -    logging.info('Attempting to log in...')
> -    if not proxy.login():
> -        logging.error('Could not log in.')
> -        sys.exit(1)
> -    logging.info('Successfully logged in.')
>  
>      if request_path:
> +        logging.info('Attempting to log in...')
> +        if not proxy.login():
> +            logging.error('Could not log in.')
> +            sys.exit(1)
> +        logging.info('Successfully logged in.')
>          logging.info('Creating a new test session and downloading vectors...')
>          test_session = proxy.register()
>          if not test_session:


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] tools: add jwt renewal function to acvp_tool
  2023-06-26 21:36 [PATCH v2] tools: add jwt renewal function to acvp_tool jspewock
  2023-06-27 16:18 ` Aaron Conole
@ 2023-06-27 16:20 ` Aaron Conole
  2023-07-03  6:44   ` Ali Alnubani
  1 sibling, 1 reply; 7+ messages in thread
From: Aaron Conole @ 2023-06-27 16:20 UTC (permalink / raw)
  To: Ali Alnubani; +Cc: ci

Hi Ali,

This patch didn't appear at the patches.dpdk.org/project/ci/list/

Is there something we need to do (or do I need to be logged in) to have
them show up?

-Aaron

jspewock@iol.unh.edu writes:

> From: Jeremy Spewock <jspewock@iol.unh.edu>
>
> Adds a method that follows the process for renewing your jwt according
> to NIST API documentation. This way, if there are load issues and it
> takes too long to get vectors back with multi-algorithm testing, the
> script will always handle the jwt expiring.
>
> Also added a maximum number of renewals so that the script cannot run
> infinitely.
>
> Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu>
> ---
>  tools/acvp/acvp_tool.py | 71 ++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 63 insertions(+), 8 deletions(-)
>  mode change 100755 => 100644 tools/acvp/acvp_tool.py
>
> diff --git a/tools/acvp/acvp_tool.py b/tools/acvp/acvp_tool.py
> old mode 100755
> new mode 100644
> index 40d2f2f..a28760d
> --- a/tools/acvp/acvp_tool.py
> +++ b/tools/acvp/acvp_tool.py
> @@ -1,7 +1,7 @@
>  #!/usr/bin/env python3
>  
>  # SPDX-License-Identifier: BSD-3-Clause
> -# Copyright 2022 The University of New Hampshire
> +# Copyright 2023 The University of New Hampshire
>  
>  import hashlib
>  import sys
> @@ -36,6 +36,8 @@ class ACVPProxy:
>          self.totp_path: str = totp_path
>          self.login_data: Optional[Dict[str, Any]] = None
>          self.session_data: Optional[Dict[str, Any]] = None
> +        self.retries: int = 0
> +        self.max_retries: int = 2
>  
>          with open(config_path, 'r') as f:
>              self.config: Any = json.load(f)
> @@ -70,7 +72,13 @@ class ACVPProxy:
>                  cert=self.cert,
>                  headers={'Authorization': f'Bearer {token}'}
>              )
> -            if not response.ok:
> +            if response.status_code == 401:
> +                if self.__renew_jwt():
> +                    token = self.session_data['jwt']
> +                    continue
> +                logging.error("Failed to renew expired jwt")
> +                return None
> +            elif not response.ok:
>                  logging.error(f'Failed to fetch vector set {url}')
>                  logging.error(json.dumps(response.json(), indent=4))
>                  return None
> @@ -85,6 +93,35 @@ class ACVPProxy:
>              logging.info(f'Downloaded vector set {url}')
>              return vector_set_json
>  
> +    def __renew_jwt(self) -> bool:
> +        """Renews the jwt in session_data.
> +
> +        JWTs provided by the NIST API last 30 minutes which can cause this
> +        script to fail even with good data. This method renews the jwt using
> +        the login endpoint.
> +
> +        @return: True if successfully renewed token
> +        """
> +        if self.retries >= self.max_retries:
> +            logging.error("Maximum number of jwt renewals has been reached.")
> +            return False
> +        response = requests.post(
> +            url=f'{self.config["url"]}/acvp/v1/login',
> +            json=[
> +                {'acvVersion': '1.0'},
> +                {
> +                'password': self.__get_totp(),
> +                'accessToken': self.session_data["jwt"]
> +                }
> +            ],
> +            cert=self.cert,
> +        )
> +        if response.ok:
> +            self.retries += 1
> +            self.session_data["jwt"] = response.json()[1].pop("accessToken")
> +            return True
> +        return False
> +
>      def login(self) -> bool:
>          """Log into the API server.
>  
> @@ -178,6 +215,12 @@ class ACVPProxy:
>                          'Authorization': f'Bearer {self.session_data["jwt"]}'
>                      }
>                  )
> +                if result.status_code == 401:
> +                    if self.__renew_jwt():
> +                        write_data[0]["jwt"] = self.session_data["jwt"]
> +                        continue
> +                    logging.error("Failed to renew jwt")
> +                    return None
>                  version, result_json = result.json()
>                  if 'retry' in result_json:
>                      duration = result_json['retry']
> @@ -208,7 +251,19 @@ class ACVPProxy:
>                  headers={'Authorization': f'Bearer {self.session_data["jwt"]}'}
>              )
>  
> -            if not response.ok:
> +            if response.status_code == 401:
> +                if self.__renew_jwt():
> +                    response = requests.post(
> +                        f'{self.config["url"]}{session_url}/vectorSets/'
> +                        f'{vector_set["vsId"]}/results',
> +                        json=[version, vector_set],
> +                        cert=self.cert,
> +                        headers={'Authorization': f'Bearer {self.session_data["jwt"]}'}
> +                    )
> +                else:
> +                    logging.error("Failed to renew jwt")
> +                    return False
> +            elif not response.ok:
>                  has_error = True
>                  logging.error(f'Could not upload vector set response for '
>                                f'vector set ID {vector_set["vsId"]}.')
> @@ -239,13 +294,13 @@ def main(request_path: Optional[str],
>          config_path=config_path,
>      )
>  
> -    logging.info('Attempting to log in...')
> -    if not proxy.login():
> -        logging.error('Could not log in.')
> -        sys.exit(1)
> -    logging.info('Successfully logged in.')
>  
>      if request_path:
> +        logging.info('Attempting to log in...')
> +        if not proxy.login():
> +            logging.error('Could not log in.')
> +            sys.exit(1)
> +        logging.info('Successfully logged in.')
>          logging.info('Creating a new test session and downloading vectors...')
>          test_session = proxy.register()
>          if not test_session:


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] tools: add jwt renewal function to acvp_tool
  2023-06-27 16:18 ` Aaron Conole
@ 2023-06-27 17:31   ` Jeremy Spewock
  2023-06-27 19:38     ` Aaron Conole
  0 siblings, 1 reply; 7+ messages in thread
From: Jeremy Spewock @ 2023-06-27 17:31 UTC (permalink / raw)
  To: Aaron Conole; +Cc: ci

[-- Attachment #1: Type: text/plain, Size: 7131 bytes --]

On Tue, Jun 27, 2023 at 12:19 PM Aaron Conole <aconole@redhat.com> wrote:

> jspewock@iol.unh.edu writes:
>
> > From: Jeremy Spewock <jspewock@iol.unh.edu>
> >
> > Adds a method that follows the process for renewing your jwt according
> > to NIST API documentation. This way, if there are load issues and it
> > takes too long to get vectors back with multi-algorithm testing, the
> > script will always handle the jwt expiring.
> >
> > Also added a maximum number of renewals so that the script cannot run
> > infinitely.
> >
> > Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu>
> > ---
>
> Hi Jeremy,
>
> Thanks for the changes, it is much easier to follow now.
>
> I ran this through 'black' and it did flag a few of your changes, but
> I don't think it is an issue here because they are single quote
> vs. double quote usage, and the usage you have is consistent with the
> rest of the file.
>
> >  tools/acvp/acvp_tool.py | 71 ++++++++++++++++++++++++++++++++++++-----
> >  1 file changed, 63 insertions(+), 8 deletions(-)
> >  mode change 100755 => 100644 tools/acvp/acvp_tool.py
>
> Was this mode change intentional?  I guess it must not be since the
> README advocates usage as:
>
>    acvp_tool.py --request $DOWNLOAD_PATH
>
> I can fix on apply if you confirm.
>

Great catch, you're right, this was not something I meant to change. I
noticed there was a conflict with file modes when I was creating and
testing the patch and I thought I fixed it to be the right one before
submitting but I suppose I did it in reverse.

if you could fix it what would be appreciated, thank you.


> > diff --git a/tools/acvp/acvp_tool.py b/tools/acvp/acvp_tool.py
> > old mode 100755
> > new mode 100644
> > index 40d2f2f..a28760d
> > --- a/tools/acvp/acvp_tool.py
> > +++ b/tools/acvp/acvp_tool.py
> > @@ -1,7 +1,7 @@
> >  #!/usr/bin/env python3
> >
> >  # SPDX-License-Identifier: BSD-3-Clause
> > -# Copyright 2022 The University of New Hampshire
> > +# Copyright 2023 The University of New Hampshire
> >
> >  import hashlib
> >  import sys
> > @@ -36,6 +36,8 @@ class ACVPProxy:
> >          self.totp_path: str = totp_path
> >          self.login_data: Optional[Dict[str, Any]] = None
> >          self.session_data: Optional[Dict[str, Any]] = None
> > +        self.retries: int = 0
> > +        self.max_retries: int = 2
> >
> >          with open(config_path, 'r') as f:
> >              self.config: Any = json.load(f)
> > @@ -70,7 +72,13 @@ class ACVPProxy:
> >                  cert=self.cert,
> >                  headers={'Authorization': f'Bearer {token}'}
> >              )
> > -            if not response.ok:
> > +            if response.status_code == 401:
> > +                if self.__renew_jwt():
> > +                    token = self.session_data['jwt']
> > +                    continue
> > +                logging.error("Failed to renew expired jwt")
> > +                return None
> > +            elif not response.ok:
> >                  logging.error(f'Failed to fetch vector set {url}')
> >                  logging.error(json.dumps(response.json(), indent=4))
> >                  return None
> > @@ -85,6 +93,35 @@ class ACVPProxy:
> >              logging.info(f'Downloaded vector set {url}')
> >              return vector_set_json
> >
> > +    def __renew_jwt(self) -> bool:
> > +        """Renews the jwt in session_data.
> > +
> > +        JWTs provided by the NIST API last 30 minutes which can cause
> this
> > +        script to fail even with good data. This method renews the jwt
> using
> > +        the login endpoint.
> > +
> > +        @return: True if successfully renewed token
> > +        """
> > +        if self.retries >= self.max_retries:
> > +            logging.error("Maximum number of jwt renewals has been
> reached.")
> > +            return False
> > +        response = requests.post(
> > +            url=f'{self.config["url"]}/acvp/v1/login',
> > +            json=[
> > +                {'acvVersion': '1.0'},
> > +                {
> > +                'password': self.__get_totp(),
> > +                'accessToken': self.session_data["jwt"]
> > +                }
> > +            ],
> > +            cert=self.cert,
> > +        )
> > +        if response.ok:
> > +            self.retries += 1
> > +            self.session_data["jwt"] =
> response.json()[1].pop("accessToken")
> > +            return True
> > +        return False
> > +
> >      def login(self) -> bool:
> >          """Log into the API server.
> >
> > @@ -178,6 +215,12 @@ class ACVPProxy:
> >                          'Authorization': f'Bearer
> {self.session_data["jwt"]}'
> >                      }
> >                  )
> > +                if result.status_code == 401:
> > +                    if self.__renew_jwt():
> > +                        write_data[0]["jwt"] = self.session_data["jwt"]
> > +                        continue
> > +                    logging.error("Failed to renew jwt")
> > +                    return None
> >                  version, result_json = result.json()
> >                  if 'retry' in result_json:
> >                      duration = result_json['retry']
> > @@ -208,7 +251,19 @@ class ACVPProxy:
> >                  headers={'Authorization': f'Bearer
> {self.session_data["jwt"]}'}
> >              )
> >
> > -            if not response.ok:
> > +            if response.status_code == 401:
> > +                if self.__renew_jwt():
> > +                    response = requests.post(
> > +                        f'{self.config["url"]}{session_url}/vectorSets/'
> > +                        f'{vector_set["vsId"]}/results',
> > +                        json=[version, vector_set],
> > +                        cert=self.cert,
> > +                        headers={'Authorization': f'Bearer
> {self.session_data["jwt"]}'}
> > +                    )
> > +                else:
> > +                    logging.error("Failed to renew jwt")
> > +                    return False
> > +            elif not response.ok:
> >                  has_error = True
> >                  logging.error(f'Could not upload vector set response
> for '
> >                                f'vector set ID {vector_set["vsId"]}.')
> > @@ -239,13 +294,13 @@ def main(request_path: Optional[str],
> >          config_path=config_path,
> >      )
> >
> > -    logging.info('Attempting to log in...')
> > -    if not proxy.login():
> > -        logging.error('Could not log in.')
> > -        sys.exit(1)
> > -    logging.info('Successfully logged in.')
> >
> >      if request_path:
> > +        logging.info('Attempting to log in...')
> > +        if not proxy.login():
> > +            logging.error('Could not log in.')
> > +            sys.exit(1)
> > +        logging.info('Successfully logged in.')
> >          logging.info('Creating a new test session and downloading
> vectors...')
> >          test_session = proxy.register()
> >          if not test_session:
>
>

[-- Attachment #2: Type: text/html, Size: 10464 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] tools: add jwt renewal function to acvp_tool
  2023-06-27 17:31   ` Jeremy Spewock
@ 2023-06-27 19:38     ` Aaron Conole
  0 siblings, 0 replies; 7+ messages in thread
From: Aaron Conole @ 2023-06-27 19:38 UTC (permalink / raw)
  To: Jeremy Spewock; +Cc: ci

Jeremy Spewock <jspewock@iol.unh.edu> writes:

> On Tue, Jun 27, 2023 at 12:19 PM Aaron Conole <aconole@redhat.com> wrote:
>
>  jspewock@iol.unh.edu writes:
>
>  > From: Jeremy Spewock <jspewock@iol.unh.edu>
>  >
>  > Adds a method that follows the process for renewing your jwt according
>  > to NIST API documentation. This way, if there are load issues and it
>  > takes too long to get vectors back with multi-algorithm testing, the
>  > script will always handle the jwt expiring.
>  >
>  > Also added a maximum number of renewals so that the script cannot run
>  > infinitely.
>  >
>  > Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu>
>  > ---
>
>  Hi Jeremy,
>
>  Thanks for the changes, it is much easier to follow now.
>
>  I ran this through 'black' and it did flag a few of your changes, but
>  I don't think it is an issue here because they are single quote
>  vs. double quote usage, and the usage you have is consistent with the
>  rest of the file.
>
>  >  tools/acvp/acvp_tool.py | 71 ++++++++++++++++++++++++++++++++++++-----
>  >  1 file changed, 63 insertions(+), 8 deletions(-)
>  >  mode change 100755 => 100644 tools/acvp/acvp_tool.py
>
>  Was this mode change intentional?  I guess it must not be since the
>  README advocates usage as:
>
>     acvp_tool.py --request $DOWNLOAD_PATH
>
>  I can fix on apply if you confirm.
>
> Great catch, you're right, this was not something I meant to change. I noticed there was a conflict with file
> modes when I was creating and testing the patch and I thought I fixed it to be the right one before submitting
> but I suppose I did it in reverse. 
>
> if you could fix it what would be appreciated, thank you.

Thanks - fixed up and applied.

>  > diff --git a/tools/acvp/acvp_tool.py b/tools/acvp/acvp_tool.py
>  > old mode 100755
>  > new mode 100644
>  > index 40d2f2f..a28760d
>  > --- a/tools/acvp/acvp_tool.py
>  > +++ b/tools/acvp/acvp_tool.py
>  > @@ -1,7 +1,7 @@
>  >  #!/usr/bin/env python3
>  >  
>  >  # SPDX-License-Identifier: BSD-3-Clause
>  > -# Copyright 2022 The University of New Hampshire
>  > +# Copyright 2023 The University of New Hampshire
>  >  
>  >  import hashlib
>  >  import sys
>  > @@ -36,6 +36,8 @@ class ACVPProxy:
>  >          self.totp_path: str = totp_path
>  >          self.login_data: Optional[Dict[str, Any]] = None
>  >          self.session_data: Optional[Dict[str, Any]] = None
>  > +        self.retries: int = 0
>  > +        self.max_retries: int = 2
>  >  
>  >          with open(config_path, 'r') as f:
>  >              self.config: Any = json.load(f)
>  > @@ -70,7 +72,13 @@ class ACVPProxy:
>  >                  cert=self.cert,
>  >                  headers={'Authorization': f'Bearer {token}'}
>  >              )
>  > -            if not response.ok:
>  > +            if response.status_code == 401:
>  > +                if self.__renew_jwt():
>  > +                    token = self.session_data['jwt']
>  > +                    continue
>  > +                logging.error("Failed to renew expired jwt")
>  > +                return None
>  > +            elif not response.ok:
>  >                  logging.error(f'Failed to fetch vector set {url}')
>  >                  logging.error(json.dumps(response.json(), indent=4))
>  >                  return None
>  > @@ -85,6 +93,35 @@ class ACVPProxy:
>  >              logging.info(f'Downloaded vector set {url}')
>  >              return vector_set_json
>  >  
>  > +    def __renew_jwt(self) -> bool:
>  > +        """Renews the jwt in session_data.
>  > +
>  > +        JWTs provided by the NIST API last 30 minutes which can cause this
>  > +        script to fail even with good data. This method renews the jwt using
>  > +        the login endpoint.
>  > +
>  > +        @return: True if successfully renewed token
>  > +        """
>  > +        if self.retries >= self.max_retries:
>  > +            logging.error("Maximum number of jwt renewals has been reached.")
>  > +            return False
>  > +        response = requests.post(
>  > +            url=f'{self.config["url"]}/acvp/v1/login',
>  > +            json=[
>  > +                {'acvVersion': '1.0'},
>  > +                {
>  > +                'password': self.__get_totp(),
>  > +                'accessToken': self.session_data["jwt"]
>  > +                }
>  > +            ],
>  > +            cert=self.cert,
>  > +        )
>  > +        if response.ok:
>  > +            self.retries += 1
>  > +            self.session_data["jwt"] = response.json()[1].pop("accessToken")
>  > +            return True
>  > +        return False
>  > +
>  >      def login(self) -> bool:
>  >          """Log into the API server.
>  >  
>  > @@ -178,6 +215,12 @@ class ACVPProxy:
>  >                          'Authorization': f'Bearer {self.session_data["jwt"]}'
>  >                      }
>  >                  )
>  > +                if result.status_code == 401:
>  > +                    if self.__renew_jwt():
>  > +                        write_data[0]["jwt"] = self.session_data["jwt"]
>  > +                        continue
>  > +                    logging.error("Failed to renew jwt")
>  > +                    return None
>  >                  version, result_json = result.json()
>  >                  if 'retry' in result_json:
>  >                      duration = result_json['retry']
>  > @@ -208,7 +251,19 @@ class ACVPProxy:
>  >                  headers={'Authorization': f'Bearer {self.session_data["jwt"]}'}
>  >              )
>  >  
>  > -            if not response.ok:
>  > +            if response.status_code == 401:
>  > +                if self.__renew_jwt():
>  > +                    response = requests.post(
>  > +                        f'{self.config["url"]}{session_url}/vectorSets/'
>  > +                        f'{vector_set["vsId"]}/results',
>  > +                        json=[version, vector_set],
>  > +                        cert=self.cert,
>  > +                        headers={'Authorization': f'Bearer {self.session_data["jwt"]}'}
>  > +                    )
>  > +                else:
>  > +                    logging.error("Failed to renew jwt")
>  > +                    return False
>  > +            elif not response.ok:
>  >                  has_error = True
>  >                  logging.error(f'Could not upload vector set response for '
>  >                                f'vector set ID {vector_set["vsId"]}.')
>  > @@ -239,13 +294,13 @@ def main(request_path: Optional[str],
>  >          config_path=config_path,
>  >      )
>  >  
>  > -    logging.info('Attempting to log in...')
>  > -    if not proxy.login():
>  > -        logging.error('Could not log in.')
>  > -        sys.exit(1)
>  > -    logging.info('Successfully logged in.')
>  >  
>  >      if request_path:
>  > +        logging.info('Attempting to log in...')
>  > +        if not proxy.login():
>  > +            logging.error('Could not log in.')
>  > +            sys.exit(1)
>  > +        logging.info('Successfully logged in.')
>  >          logging.info('Creating a new test session and downloading vectors...')
>  >          test_session = proxy.register()
>  >          if not test_session:


^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH v2] tools: add jwt renewal function to acvp_tool
  2023-06-27 16:20 ` Aaron Conole
@ 2023-07-03  6:44   ` Ali Alnubani
  2023-07-06 18:58     ` Aaron Conole
  0 siblings, 1 reply; 7+ messages in thread
From: Ali Alnubani @ 2023-07-03  6:44 UTC (permalink / raw)
  To: Aaron Conole; +Cc: ci

> -----Original Message-----
> From: Aaron Conole <aconole@redhat.com>
> Sent: Tuesday, June 27, 2023 7:20 PM
> To: Ali Alnubani <alialnu@nvidia.com>
> Cc: ci@dpdk.org
> Subject: Re: [PATCH v2] tools: add jwt renewal function to acvp_tool
> 
> Hi Ali,
> 
> This patch didn't appear at the patches.dpdk.org/project/ci/list/
> 
> Is there something we need to do (or do I need to be logged in) to have
> them show up?
> 

Hi Aaron,

Thank you for bringing this to my attention, and apologies for the delay.
Turns out I forgot to subscribe the Patchwork user to the CI mailing list. Should be resolved now.
Please let me know if you see the issue again.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] tools: add jwt renewal function to acvp_tool
  2023-07-03  6:44   ` Ali Alnubani
@ 2023-07-06 18:58     ` Aaron Conole
  0 siblings, 0 replies; 7+ messages in thread
From: Aaron Conole @ 2023-07-06 18:58 UTC (permalink / raw)
  To: Ali Alnubani; +Cc: ci

Ali Alnubani <alialnu@nvidia.com> writes:

>> -----Original Message-----
>> From: Aaron Conole <aconole@redhat.com>
>> Sent: Tuesday, June 27, 2023 7:20 PM
>> To: Ali Alnubani <alialnu@nvidia.com>
>> Cc: ci@dpdk.org
>> Subject: Re: [PATCH v2] tools: add jwt renewal function to acvp_tool
>> 
>> Hi Ali,
>> 
>> This patch didn't appear at the patches.dpdk.org/project/ci/list/
>> 
>> Is there something we need to do (or do I need to be logged in) to have
>> them show up?
>> 
>
> Hi Aaron,
>
> Thank you for bringing this to my attention, and apologies for the delay.
> Turns out I forgot to subscribe the Patchwork user to the CI mailing list. Should be resolved now.
> Please let me know if you see the issue again.

Thanks - will keep an eye on it.


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-07-06 18:59 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-26 21:36 [PATCH v2] tools: add jwt renewal function to acvp_tool jspewock
2023-06-27 16:18 ` Aaron Conole
2023-06-27 17:31   ` Jeremy Spewock
2023-06-27 19:38     ` Aaron Conole
2023-06-27 16:20 ` Aaron Conole
2023-07-03  6:44   ` Ali Alnubani
2023-07-06 18:58     ` Aaron Conole

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).