diff --git a/ChangeLog.md b/ChangeLog.md index 5e0c8bc..a2022af 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,6 +5,12 @@ # CaPyCli - Clearing Automation Python Command Line Tool for SW360 +## 2.12.0 + +* Because of security reasons `-client_id` and `-client_secret` should only + be considered as fallback. Primary source for this information are the + environment variables `SW360Client_id` and `SW360Client_secret`. + ## 2.12.0.dev1 * Fix for issue 218: Bug when using capycli bom map -o outmap (v2.11.1). diff --git a/capycli/bom/check_bom.py b/capycli/bom/check_bom.py index 53b98e1..3195b5c 100644 --- a/capycli/bom/check_bom.py +++ b/capycli/bom/check_bom.py @@ -196,19 +196,41 @@ def run(self, args: Any) -> None: if self._bom_has_items_without_id(bom): print("There are SBOM items without Sw360 id - searching per name may take a little bit longer...") - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=False) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) - - if args.sw360_token and args.oauth2: + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=False) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) + + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): print_red("ERROR: login failed!") diff --git a/capycli/bom/check_bom_item_status.py b/capycli/bom/check_bom_item_status.py index f262c95..1374fbf 100644 --- a/capycli/bom/check_bom_item_status.py +++ b/capycli/bom/check_bom_item_status.py @@ -188,6 +188,7 @@ def run(self, args: Any) -> None: print("-all show status of all versions of the component") print("-client_id CLIENT_ID the SW360 client_id to be used for token generation") print("-client_secret CLIENT_SECRET the SW360 client_secret to be used for token generation") + print("-v be verbose") return if not args.inputfile: @@ -211,19 +212,41 @@ def run(self, args: Any) -> None: if self._bom_has_items_without_id(bom): print("There are SBOM items without Sw360 id - searching per name may take a little bit longer...") - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=False) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) - - if args.sw360_token and args.oauth2: + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=False) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) + + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): print_red("ERROR: login failed!") diff --git a/capycli/bom/create_components.py b/capycli/bom/create_components.py index eab2b66..60a9a4a 100644 --- a/capycli/bom/create_components.py +++ b/capycli/bom/create_components.py @@ -56,6 +56,7 @@ class BomCreateComponents(capycli.common.script_base.ScriptBase): " ignore prefixes like \"2:\" (epoch) and suffixes like \".debian\"", " -client_id CLIENT_ID the SW360 client_id to be used for token generation", " -client_secret CLIENT_SECRET the SW360 client_secret to be used for token generation" + " -v be verbose" ] def __init__(self, onlyCreateReleases: bool = False) -> None: @@ -777,19 +778,41 @@ def run(self, args: Any) -> None: print_text("Using relaxed debian version checks") self.relaxed_debian_parsing = True - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=True) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=True) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) - if args.sw360_token and args.oauth2: + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): print_red("ERROR: login failed!") diff --git a/capycli/bom/findsources.py b/capycli/bom/findsources.py index caf709e..0d32df0 100644 --- a/capycli/bom/findsources.py +++ b/capycli/bom/findsources.py @@ -772,16 +772,41 @@ def run(self, args: Any) -> None: self.sw360_url = args.sw360_url if self.sw360_url: - if args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=False) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=False) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) + + if args.sw360_token and args.oauth2 and args.verbose: + self.analyze_token(args.sw360_token) + print_text("") self.login( token=args.sw360_token, url=self.sw360_url, oauth2=args.oauth2) diff --git a/capycli/bom/map_bom.py b/capycli/bom/map_bom.py index 313436a..357ffaa 100644 --- a/capycli/bom/map_bom.py +++ b/capycli/bom/map_bom.py @@ -935,19 +935,41 @@ def run(self, args: Any) -> None: if self.verbosity > 1: print_text(" ", self.get_comp_count_text(sbom), "read from SBOM") - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=False) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text("\n Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=False) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) - if args.sw360_token and args.oauth2: + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") print_text(" Checking access to SW360...") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): diff --git a/capycli/common/script_base.py b/capycli/common/script_base.py index e535f08..c256ce7 100644 --- a/capycli/common/script_base.py +++ b/capycli/common/script_base.py @@ -79,7 +79,7 @@ def analyze_token(self, token: str) -> None: # alg = RS256 decoded = jwt.decode(token, algorithms=["HS256"], options={"verify_signature": False}) # type: ignore if "scope" in decoded: - scope = decoded["scope"] + scope = str(decoded["scope"]) if scope.lower().find("write") >= 0: print_text(" Token has write permissions") else: diff --git a/capycli/main/options.py b/capycli/main/options.py index c27cffb..00cd597 100644 --- a/capycli/main/options.py +++ b/capycli/main/options.py @@ -154,6 +154,7 @@ def register_options(self) -> None: self.parser.add_argument( "-v", + "--verbose", help="be verbose", dest="verbose", action="store_true", diff --git a/capycli/project/check_prerequisites.py b/capycli/project/check_prerequisites.py index 8ac68cc..ac1e9db 100644 --- a/capycli/project/check_prerequisites.py +++ b/capycli/project/check_prerequisites.py @@ -315,19 +315,41 @@ def run(self, args: Any) -> None: print(" -client_secret CLIENT_SECRET the SW360 client_secret to be used for token generation") return - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=False) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=False) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) - if args.sw360_token and args.oauth2: + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): print_red("ERROR: login failed!") diff --git a/capycli/project/create_project.py b/capycli/project/create_project.py index bb5b7ce..cff1b7f 100644 --- a/capycli/project/create_project.py +++ b/capycli/project/create_project.py @@ -319,22 +319,23 @@ def run(self, args: Any) -> None: " - Create or update a project on SW360\n") if args.help: - print("usage: CaPyCli project create -i bom.json -o bom_created.json [-source ]") - print("") - print("optional arguments:") - print(" -i INPUTFILE, bom file to read from (JSON)") - print(" -t SW360_TOKEN, use this token for access to SW360") - print(" -oa, --oauth2 this is an oauth2 token") - print(" -url SW360_URL use this URL for access to SW360") - print(" -name NAME name of the project") - print(" -version VERSION, version of the project") - print(" -id PROJECT_ID SW360 id of the project, supersedes name and version parameters") - print(" -old-version previous version") - print(" -source projectinfo.json additional information about the project to be created") - print(" -pms project mainline state for releases in a newly created project") - print(" --copy_from PROJECT_ID copy the project with the given id and the update it") - print(" -client_id CLIENT_ID the SW360 client_id to be used for token generation") - print(" -client_secret CLIENT_SECRET the SW360 client_secret to be used for token generation") + print_text("usage: CaPyCli project create -i bom.json -o bom_created.json [-source ]") + print_text("") + print_text("optional arguments:") + print_text(" -i INPUTFILE, bom file to read from (JSON)") + print_text(" -t SW360_TOKEN, use this token for access to SW360") + print_text(" -oa, --oauth2 this is an oauth2 token") + print_text(" -url SW360_URL use this URL for access to SW360") + print_text(" -name NAME name of the project") + print_text(" -version VERSION, version of the project") + print_text(" -id PROJECT_ID SW360 id of the project, supersedes name and version parameters") + print_text(" -old-version previous version") + print_text(" -source projectinfo.json additional information about the project to be created") + print_text(" -pms project mainline state for releases in a newly created project") + print_text(" --copy_from PROJECT_ID copy the project with the given id and the update it") + print_text(" -client_id CLIENT_ID the SW360 client_id to be used for token generation") + print_text(" -client_secret CLIENT_SECRET the SW360 client_secret to be used for token generation") + print_text(" --verbose be verbose") return if not args.inputfile: @@ -373,19 +374,41 @@ def run(self, args: Any) -> None: print_text("Project version will be updated with version: " + args.old_version) is_update_version = True - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=True) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) - - if args.sw360_token and args.oauth2: + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=True) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) + + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): print_red("ERROR: login failed!") diff --git a/capycli/project/find_project.py b/capycli/project/find_project.py index 8033bfe..ee95859 100644 --- a/capycli/project/find_project.py +++ b/capycli/project/find_project.py @@ -7,6 +7,7 @@ # ------------------------------------------------------------------------------- import logging +import os import sys import traceback from typing import Any, Dict, Optional @@ -122,19 +123,41 @@ def run(self, args: Any) -> None: print(" -client_secret CLIENT_SECRET the SW360 client_secret to be used for token generation") return - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=False) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=False) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) - if args.sw360_token and args.oauth2: + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): print_red("ERROR: login failed!") diff --git a/capycli/project/get_license_info.py b/capycli/project/get_license_info.py index 890ad77..6e2684b 100644 --- a/capycli/project/get_license_info.py +++ b/capycli/project/get_license_info.py @@ -241,19 +241,41 @@ def run(self, args: Any) -> None: print_red("Input file not found!") sys.exit(ResultCode.RESULT_FILE_NOT_FOUND) - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=False) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) - - if args.sw360_token and args.oauth2: + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=False) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) + + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): print_red("ERROR: login failed!") diff --git a/capycli/project/project_component_check.py b/capycli/project/project_component_check.py index f1a3122..5f62851 100644 --- a/capycli/project/project_component_check.py +++ b/capycli/project/project_component_check.py @@ -7,6 +7,7 @@ # ------------------------------------------------------------------------------- import logging +import os import sys from typing import Any @@ -150,19 +151,41 @@ def run(self, args: Any) -> None: self.component_check.files_to_ignore = self.component_check.component_check_list.get("files_to_ignore", []) print_text(f" {len(self.component_check.files_to_ignore)} components will be ignored.") - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=False) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) - - if args.sw360_token and args.oauth2: + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=False) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) + + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): print_red("ERROR: login failed!") diff --git a/capycli/project/show_ecc.py b/capycli/project/show_ecc.py index 5d2e60f..01bca91 100644 --- a/capycli/project/show_ecc.py +++ b/capycli/project/show_ecc.py @@ -7,6 +7,7 @@ # ------------------------------------------------------------------------------- import logging +import os import sys from typing import Any, Dict @@ -178,21 +179,44 @@ def run(self, args: Any) -> None: print(" -o OUTPUTFILE output file to write project details to") print(" -client_id CLIENT_ID the SW360 client_id to be used for token generation") print(" -client_secret CLIENT_SECRET the SW360 client_secret to be used for token generation") + print(" -v be verbose") return - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=False) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) - - if args.sw360_token and args.oauth2: + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=False) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) + + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): print_red("ERROR: login failed!") diff --git a/capycli/project/show_licenses.py b/capycli/project/show_licenses.py index 06e1697..44ed627 100644 --- a/capycli/project/show_licenses.py +++ b/capycli/project/show_licenses.py @@ -185,6 +185,7 @@ def show_command_help(self) -> None: -version version of the project, component or release -client_id CLIENT_ID the SW360 client_id to be used for token generation -client_secret CLIENT_SECRET the SW360 client_secret to be used for token generation + -v be verbose """) print() @@ -208,19 +209,41 @@ def run(self, args: Any) -> None: self.show_command_help() return - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=False) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=False) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) - if args.sw360_token and args.oauth2: + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): print_red("ERROR: login failed!") diff --git a/capycli/project/show_project.py b/capycli/project/show_project.py index 03e75aa..715f654 100644 --- a/capycli/project/show_project.py +++ b/capycli/project/show_project.py @@ -7,6 +7,7 @@ # ------------------------------------------------------------------------------- import logging +import os import sys from typing import Any, Dict, Optional @@ -198,21 +199,44 @@ def run(self, args: Any) -> None: print(" -o OUTPUTFILE output file to write project details to") print(" -client_id CLIENT_ID the SW360 client_id to be used for token generation") print(" -client_secret CLIENT_SECRET the SW360 client_secret to be used for token generation") + print(" -v be verbose") return - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=False) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) - - if args.sw360_token and args.oauth2: + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=False) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) + + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): print_red("ERROR: login failed!") diff --git a/capycli/project/show_vulnerabilities.py b/capycli/project/show_vulnerabilities.py index e807835..accdaac 100644 --- a/capycli/project/show_vulnerabilities.py +++ b/capycli/project/show_vulnerabilities.py @@ -7,6 +7,7 @@ # ------------------------------------------------------------------------------- import logging +import os import sys from typing import Any, Dict, Optional @@ -247,19 +248,41 @@ def run(self, args: Any) -> None: if args.verbose: print("Output format is", self.format) - if not args.sw360_token and args.client_id and args.client_secret: - print_text("Creating token using client id and secret...") - kc = SW360Keycloak(args.sw360_url) - args.sw360_token = kc.get_keycloak_token(args.client_id, args.client_secret, write_access=False) - if args.sw360_token: - args.oauth2 = True - print_text(" Got token.") - else: - print_red(" Failed to get token!") - sys.exit(ResultCode.RESULT_AUTH_ERROR) + if not args.sw360_token: + # command line argument precede environment variables + client_id = args.client_id + client_secret = args.client_secret + + if not args.client_id and (not args.client_secret): + # look for environment variables + client_id = os.getenv("SW360Client_id") + client_secret = os.getenv("SW360Client_secret") + if client_id and client_secret and args.verbose: + print_text(" Found client id and client secret in environment variables.") + + if client_id and client_secret: + url = args.sw360_url + if not url: + url = os.environ.get("SW360ServerUrl", "") + if not url: + print_red(" SW360 URL not specified!") + sys.exit(ResultCode.RESULT_COMMAND_ERROR) + + if args.verbose: + print_text(" Creating token using client id and secret...") + kc = SW360Keycloak(url) + args.sw360_token = kc.get_keycloak_token(client_id, client_secret, write_access=False) + if args.sw360_token: + args.oauth2 = True + if args.verbose: + print_text(" Got token.") + else: + print_red(" Failed to get token!") + sys.exit(ResultCode.RESULT_AUTH_ERROR) - if args.sw360_token and args.oauth2: + if args.sw360_token and args.oauth2 and args.verbose: self.analyze_token(args.sw360_token) + print_text("") if not self.login(token=args.sw360_token, url=args.sw360_url, oauth2=args.oauth2): print_red("ERROR: login failed!") diff --git a/tests/test_bom_create_components.py b/tests/test_bom_create_components.py index ceb1ae4..ec277e8 100644 --- a/tests/test_bom_create_components.py +++ b/tests/test_bom_create_components.py @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------------- -# Copyright (c) 2021-2025 Siemens +# Copyright (c) 2021-2026 Siemens # All Rights Reserved. # Author: gernot.hillier@siemens.com, thomas.graf@siemens.com # @@ -10,6 +10,7 @@ Most functionality is tested in test_bom_create_releases.py""" import os +from unittest import mock import responses from cyclonedx.model import ExternalReferenceType @@ -189,7 +190,12 @@ def test_no_login(self) -> None: args.verbose = True try: - sut.run(args) + # mock: remove environment variables + with mock.patch.dict(os.environ): + os.environ["SW360Client_id"] = "" + os.environ["SW360Client_secret"] = "" + sut.run(args) + self.assertTrue(False, "Failed to report login failure") except SystemExit as ex: self.assertEqual(ResultCode.RESULT_AUTH_ERROR, ex.code) diff --git a/tests/test_bom_map2.py b/tests/test_bom_map2.py index 430ad84..42e2fc3 100644 --- a/tests/test_bom_map2.py +++ b/tests/test_bom_map2.py @@ -1136,7 +1136,12 @@ def test_no_login(self) -> None: args.nocache = True try: - sut.run(args) + # mock: remove environment variables + with unittest.mock.patch.dict(os.environ): + os.environ["SW360Client_id"] = "" + os.environ["SW360Client_secret"] = "" + sut.run(args) + self.assertTrue(False, "Failed to report login failure") except SystemExit as ex: self.assertEqual(ResultCode.RESULT_AUTH_ERROR, ex.code) diff --git a/tests/test_create_project.py b/tests/test_create_project.py index a7c206d..22c2320 100644 --- a/tests/test_create_project.py +++ b/tests/test_create_project.py @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------------- -# Copyright (c) 2023-2025 Siemens +# Copyright (c) 2023-2026 Siemens # All Rights Reserved. # Author: thomas.graf@siemens.com # @@ -9,6 +9,7 @@ import json import os from typing import Any, Dict, Tuple +from unittest import mock import responses import responses.matchers @@ -219,7 +220,12 @@ def test_no_login(self) -> None: args.inputfile = os.path.join(os.path.dirname(__file__), "fixtures", TestCreateProject.INPUTFILE) try: - sut.run(args) + # mock: remove environment variables + with mock.patch.dict(os.environ): + os.environ["SW360Client_id"] = "" + os.environ["SW360Client_secret"] = "" + sut.run(args) + self.assertTrue(False, "Failed to report login failure") except SystemExit as ex: self.assertEqual(ResultCode.RESULT_AUTH_ERROR, ex.code) diff --git a/tests/test_project_component_check.py b/tests/test_project_component_check.py index a2a09e9..0e84801 100644 --- a/tests/test_project_component_check.py +++ b/tests/test_project_component_check.py @@ -6,8 +6,9 @@ # SPDX-License-Identifier: MIT # ------------------------------------------------------------------------------- +import os from typing import Any, Dict -from unittest.mock import MagicMock +from unittest.mock import MagicMock, patch import responses @@ -49,7 +50,12 @@ def test_no_login(self) -> None: args.verbose = True try: - sut.run(args) + # mock: remove environment variables + with patch.dict(os.environ): + os.environ["SW360Client_id"] = "" + os.environ["SW360Client_secret"] = "" + sut.run(args) + self.assertTrue(False, "Failed to report login failure") except SystemExit as ex: self.assertEqual(ResultCode.RESULT_AUTH_ERROR, ex.code) diff --git a/tests/test_show_ecc.py b/tests/test_show_ecc.py index 18830d3..2cf97bc 100644 --- a/tests/test_show_ecc.py +++ b/tests/test_show_ecc.py @@ -8,6 +8,7 @@ import os from typing import Any, Dict +from unittest import mock import responses @@ -46,7 +47,12 @@ def test_no_login(self) -> None: args.verbose = True try: - sut.run(args) + # mock: remove environment variables + with mock.patch.dict(os.environ): + os.environ["SW360Client_id"] = "" + os.environ["SW360Client_secret"] = "" + sut.run(args) + self.assertTrue(False, "Failed to report login failure") except SystemExit as ex: self.assertEqual(ResultCode.RESULT_AUTH_ERROR, ex.code) diff --git a/tests/test_show_licenses.py b/tests/test_show_licenses.py index 45d6dd0..323317e 100644 --- a/tests/test_show_licenses.py +++ b/tests/test_show_licenses.py @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------------- -# Copyright (c) 2022-2023 Siemens +# Copyright (c) 2022-2026 Siemens # All Rights Reserved. # Author: thomas.graf@siemens.com, rayk.bajohr@siemens.com # @@ -8,6 +8,7 @@ import os import shutil +from unittest import mock import responses @@ -44,7 +45,12 @@ def test_no_login(self) -> None: args.verbose = True try: - sut.run(args) + # mock: remove environment variables + with mock.patch.dict(os.environ): + os.environ["SW360Client_id"] = "" + os.environ["SW360Client_secret"] = "" + sut.run(args) + self.assertTrue(False, "Failed to report login failure") except SystemExit as ex: self.assertEqual(ResultCode.RESULT_AUTH_ERROR, ex.code) diff --git a/tests/test_show_project.py b/tests/test_show_project.py index b6c5146..42a60ac 100644 --- a/tests/test_show_project.py +++ b/tests/test_show_project.py @@ -8,7 +8,7 @@ import os from typing import Any, Dict -from unittest.mock import MagicMock +from unittest.mock import MagicMock, patch import responses @@ -52,7 +52,12 @@ def test_no_login(self) -> None: args.verbose = True try: - sut.run(args) + # mock: remove environment variables + with patch.dict(os.environ): + os.environ["SW360Client_id"] = "" + os.environ["SW360Client_secret"] = "" + sut.run(args) + self.assertTrue(False, "Failed to report login failure") except SystemExit as ex: self.assertEqual(ResultCode.RESULT_AUTH_ERROR, ex.code) diff --git a/tests/test_show_vulnerabilities.py b/tests/test_show_vulnerabilities.py index 2a8a1ba..d34aca1 100644 --- a/tests/test_show_vulnerabilities.py +++ b/tests/test_show_vulnerabilities.py @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------------- -# Copyright (c) 2022-2023 Siemens +# Copyright (c) 2022-2026 Siemens # All Rights Reserved. # Author: thomas.graf@siemens.com, rayk.bajohr@siemens.com # @@ -8,6 +8,7 @@ import os from typing import Any, Dict +from unittest import mock import responses @@ -46,7 +47,12 @@ def test_no_login(self) -> None: args.verbose = True try: - sut.run(args) + # mock: remove environment variables + with mock.patch.dict(os.environ): + os.environ["SW360Client_id"] = "" + os.environ["SW360Client_secret"] = "" + sut.run(args) + self.assertTrue(False, "Failed to report login failure") except SystemExit as ex: self.assertEqual(ResultCode.RESULT_AUTH_ERROR, ex.code) @@ -358,4 +364,4 @@ def test_check_report(self) -> None: if __name__ == "__main__": APP = TestShowSecurityVulnerability() - APP.test_project_not_found() + APP.test_no_login()