From 95ac5b18fe272b655005de5936ac5df33867496f Mon Sep 17 00:00:00 2001 From: Tannaz Vahidi Date: Fri, 11 Oct 2024 11:25:34 +0200 Subject: [PATCH] `lobster-codebeamer` uses authentication token (#70) One new argument to pass the token has been added to lobster-codebeamer. The user can also define the token in cb config file. Update lobster-codebeamer README Update the documentation about the configuration file of the `lobster-codebeamer` tool: - update section about `refs` - update section about `token` Resolves https://github.com/bmw-software-engineering/lobster/issues/69 --------- Co-authored-by: Philipp Wullstein-Kammler --- CHANGELOG.md | 3 + lobster/tools/codebeamer/codebeamer.py | 49 ++++++++++---- packages/lobster-tool-codebeamer/README.md | 77 +++++++++++++++++----- 3 files changed, 102 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b078200f..457ea869 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ ### 0.9.18-dev +* The `lobster-codebeamer` tool now uses an authentication token. + Token can be added either in the config file or as an argument. + * The `lobster-python` tool adds the counter logic to the function identifier. This improves the situations where different functions have the same name. Line numbers are no longer used in the identifier. diff --git a/lobster/tools/codebeamer/codebeamer.py b/lobster/tools/codebeamer/codebeamer.py index 57ab9b02..2b9d7746 100755 --- a/lobster/tools/codebeamer/codebeamer.py +++ b/lobster/tools/codebeamer/codebeamer.py @@ -50,6 +50,9 @@ from lobster.errors import Message_Handler, LOBSTER_Error from lobster.io import lobster_read, lobster_write +TOKEN = 'token' +REFERENCES = 'references' + class References(Enum): REFS = "refs" @@ -71,14 +74,28 @@ def add_refs_refrences(req, flat_values_list): } +class BearerAuth(requests.auth.AuthBase): + def __init__(self, token): + self.token = token + + def __call__(self, r): + r.headers['Authorization'] = f'Bearer {self.token}' + return r + + def query_cb_single(cb_config, url): assert isinstance(cb_config, dict) assert isinstance(url, str) try: + if cb_config["token"]: + auth = BearerAuth(cb_config["token"]) + else: + auth = (cb_config["user"], + cb_config["pass"]) + result = requests.get(url, - auth=(cb_config["user"], - cb_config["pass"]), + auth=auth, timeout=cb_config["timeout"], verify=cb_config["verify_ssl"]) except requests.exceptions.ReadTimeout: @@ -215,9 +232,9 @@ def to_lobster(cb_config, cb_item): text = None, status = status) - if cb_config.get('references'): + if cb_config.get(REFERENCES): for reference_name, displayed_chosen_names in ( - cb_config['references'].items()): + cb_config[REFERENCES].items()): if reference_name not in map_reference_name_to_function: continue @@ -272,6 +289,11 @@ def parse_cb_config(file_name): with open(file_name, "r", encoding='utf-8') as file: data = json.loads(file.read()) + json_config = {REFERENCES: {}} + + if TOKEN in data: + json_config["token"] = data.pop(TOKEN) + provided_config_keys = set(data.keys()) supported_references = set(SUPPORTED_REFERENCES) @@ -280,9 +302,9 @@ def parse_cb_config(file_name): "supported referenes: '%s'" % ', '.join(SUPPORTED_REFERENCES)) - json_config = {} for key, value in data.items(): - json_config[key] = ensure_array_of_strings(value) + json_config[REFERENCES][key] = ensure_array_of_strings(value) + return json_config @@ -322,6 +344,7 @@ def main(): ap.add_argument("--cb-root", default=os.environ.get("CB_ROOT", None)) ap.add_argument("--cb-user", default=os.environ.get("CB_USERNAME", None)) ap.add_argument("--cb-pass", default=os.environ.get("CB_PASSWORD", None)) + ap.add_argument("--cb-token", default=None) ap.add_argument("--out", default=None) options = ap.parse_args() @@ -332,6 +355,7 @@ def main(): "base" : "%s/cb/api/v3" % options.cb_root, "user" : options.cb_user, "pass" : options.cb_pass, + "token" : options.cb_token, "verify_ssl" : not options.ignore_ssl_errors, "page_size" : options.query_size, "timeout" : options.timeout, @@ -339,7 +363,7 @@ def main(): if options.config: if os.path.isfile(options.config): - cb_config["references"] = parse_cb_config(options.config) + cb_config.update(parse_cb_config(options.config)) else: ap.error("cannot open config file '%s'" % options.config) @@ -349,7 +373,8 @@ def main(): if not cb_config["root"].startswith("https://"): ap.error("codebeamer root %s must start with https://") - if cb_config["user"] is None or cb_config["pass"] is None: + if (cb_config["token"] is None and + (cb_config["user"] is None or cb_config["pass"] is None)): netrc_file = os.path.join(os.path.expanduser("~"), ".netrc") if os.path.isfile(netrc_file): @@ -359,10 +384,10 @@ def main(): print("using .netrc login for %s" % cb_config["root"]) cb_config["user"], _, cb_config["pass"] = auth - if cb_config["user"] is None: - ap.error("please set CB_USERNAME or use --cb-user") - if cb_config["pass"] is None: - ap.error("please set CB_PASSWORD or use --cb-pass") + if (cb_config["token"] is None and + (cb_config["user"] is None or cb_config["pass"] is None)): + ap.error("please set --cb-token or add your token to the config-file" + "or use --cb-user and --cb-pass") items_to_import = set() diff --git a/packages/lobster-tool-codebeamer/README.md b/packages/lobster-tool-codebeamer/README.md index 9c4b729c..06cf3545 100644 --- a/packages/lobster-tool-codebeamer/README.md +++ b/packages/lobster-tool-codebeamer/README.md @@ -14,26 +14,76 @@ requirements management tool * `lobster-codebeamer`: Extrat requirements from codebeamer. ## Configuration -This tool works with an optional config file. In it you can declare which -codebeamer fields should be used as 'refs' reference in the codebeamer file. - -For the 'refs' reference in config file you can write: - +This tool works with an optional config file. +It allows to configure the following features: + +### References +Codebeamer items can reference other items through +[Reference Fields](https://support.ptc.com/help/codebeamer/r2.1/en/index.html#page/codebeamer/user_guide/ug_reference_fields.html). +This piece of information can be extracted by the tool, and serialized into the +LOBSTER output file. +It only needs to know which fields to take into account. +Following the LOBSTER JSON schema, the item references will be added to the +`refs` property of the LOBSTER item. +Accordingly, the configuration parameter to specify the codebeamer field names +is called `refs`, too. +It can contain a single field name, or a list of field names. +Field IDs cannot be used, only the field names. + +Examples: +```json +{ + "refs" : "cb-fieldname" +} ``` +or +```json { -"refs" : "cb-fieldname" + "refs" : ["cb-fieldname"] } ``` or +```json +{ + "refs" : ["cb-fieldname1", "cb-fieldname2"] +} ``` + +### Bearer Authentication Token +It is also possible to define the Bearer authentication token in the +configuration file: +```json { -"refs" : ["cb-fieldname"] + "token" : "your-codebeamer-Bearer-token" } ``` -or +Note: +- The Bearer authentication token can also be provided as a command line + argument (use `--cb-token=your-codebeamer-Bearer-token`). +- If the token is provided in the configuration file and as command line + argument, then the configuration file takes precedence. +- If `--cb-user` or `--cb-pass` is given together with a Bearer token (either + as a command line argument or through the configuration file), then the + Bearer authentication method is used, and the username and/or password are + ignored. +- If neither a token nor a username or password are given, then the tool tries + to read the username and password from the `.netrc` file in the user's home + directory. + +### Example Configuration +Here is an example configuration file: +```json +{ + "refs" : ["derived from", "satisfied by"], + "token" : "SomeTokenStringABC123" +} +``` + +Is it also possible to define the codebeamer token in this file: ``` { -"refs" : ["cb-fieldname1", "cb-fieldname2"] +"refs" : "cb-fieldname", +"token" : "your cb-token" } ``` @@ -41,19 +91,16 @@ or There are two ways you can use this tool: -* Download all requirements mentioned by another lobster trace (this +1. Download all requirements mentioned by another lobster trace (this way you do not get a completeness check) (using `--import-tagged`) -* Download all requirements generated by a saved codebeamer query +2. Download all requirements generated by a saved codebeamer query (using `--import-query`) -* Configure the 'refs' upstream reference (this argument is optional) -(using `--config`) - ## Limitations The key limitation is item text, which is currently not -imported. However we do plan to also import item text eventually. +imported. However, we do plan to also import item text eventually. ## Copyright & License information