Fix secure credential loading for nested team-config profiles - #411
Fix secure credential loading for nested team-config profiles#411ATorrise wants to merge 3 commits into
Conversation
Signed-off-by: ATorrise <ambertorrise@gmail.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #411 +/- ##
==========================================
+ Coverage 83.06% 83.40% +0.34%
==========================================
Files 49 49
Lines 2982 2983 +1
==========================================
+ Hits 2477 2488 +11
+ Misses 505 495 -10
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
zFernand0
left a comment
There was a problem hiding this comment.
LGTM! 😋
Very good catch! 🙏
Here is a quick before and after of this fix:
Before
{'rejectUnauthorized': False, 'host': 'lpar.1', 'port': 1234}
HTTP Request has failed with status code 401.
After
{'rejectUnauthorized': False, 'host': 'lpar.1', 'port': 1234, 'user': 'dummy', 'password': 'dummy'}
HTTP Request has failed with status code 401.
I got the 401 because dummy:dummy is not valid on my system
With proper creds:
{'rejectUnauthorized': False, 'host': 'lpar.1', 'port': 1234, 'user': 'REALUSER', 'password': 'PASSWORD'}
//* //FERNAN00 JOB (IZUACCT),FERNANDO,CLASS=B,MSGCLASS=X,TYPRUN=HOLD
...
traeok
left a comment
There was a problem hiding this comment.
I noticed that even with these changes, the failure is never raised from check_missing_props, which is likely why @zFernand0 was seeing a 401 rather than an explicit error. I'd consider it out of scope for this PR, but worth a follow-up issue.
Aside from that, I left a suggestion around the modified code in an attempt to de-duplicate logic.
| for i, profile_name in enumerate(segments): | ||
| if profiles_obj is None or not isinstance(profiles_obj, dict): | ||
| break | ||
| if profile_name in profiles_obj: | ||
| profiles_obj = profiles_obj[profile_name] | ||
| if not isinstance(profiles_obj, dict): | ||
| break | ||
| if i == len(segments) - 1: | ||
| profiles_obj.setdefault("properties", {}) | ||
| profiles_obj["properties"][property_name] = value | ||
| else: | ||
| profiles_obj = profiles_obj.get("profiles", {}) |
There was a problem hiding this comment.
I know the loop is pre-existing, but this walk looks identical to find_profile. Could we just use that instead and remove this whole loop?
For example:
profile = self.find_profile(".".join(segments), self.profiles)
if isinstance(profile, dict):
profile.setdefault("properties", {})[property_name] = value
What It Does
When testing #408 i found that the way i structured my config was returning 401s
ie:
found that
__load_secure_propertieslooked for zosmf as a direct key of the mainframe profile but zosmf actually lives one level deeper, under the profiles key.the fix to config_file.py handles however many levels a config nests
test_custom_file_and_custom_profile_loading_with_nested_profile user/password values came from a plaintext override innested.zowe.config.user.json, not from the vault. So apparently no test ever exercised__load_secure_propertiesfor a profile nested more than one level deep with secure fields on the child! Added a new test (test_nested_profile_with_secure_properties_on_child) that pulls creds from the mocked vaultHow to Test
change your config to match this level of nesting when testing. verify that you get 401s on main and you can run system tests on this branch :)
Review Checklist
I certify that I have:
Additional Comments