From 8e6874d4e18919a5806c5dc057a60b3295bfce21 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Wed, 9 Oct 2024 12:34:19 -0400 Subject: [PATCH 01/61] Add design document. Signed-off-by: Gene Johnston --- docs/Design_for_selecting_auth_type.md | 199 +++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 docs/Design_for_selecting_auth_type.md diff --git a/docs/Design_for_selecting_auth_type.md b/docs/Design_for_selecting_auth_type.md new file mode 100644 index 0000000000..4ee6158433 --- /dev/null +++ b/docs/Design_for_selecting_auth_type.md @@ -0,0 +1,199 @@ +# Order of authentication in Zowe Clients + +This document identifies a design to enable users to specify the order in which credentials are selected for authentication when multiple credentials are specified by the user. + +Users may not intentionally specify multiple credentials for the same operation. However, because configuration properties can be inherited from a base profile or within nested profiles, it is possible that multiple credentials may be available when a Zowe client attempts to make a connection to a mainframe service. + +## Use cases + +A user may use the same user and password to authenticate to most of their services. It makes sense to place that user & password in a base profile so that they are automatically available to every service. This reduces redundancy and reduces maintenance efforts. If one plugin requires a token for authentication, the user would store a token value within that plugin's profile. For that plugin, both the user & password and a token will be available when Zowe CLI attempts to make a connection to that service. For this example, the token is the right choice for this service. For historical reasons, Zowe always selects a user & password over a token when both are available. The use of user & password does not give the desired results. + +When a site gradually deploys API-ML, they will very likely encounter another (but opposite) authentication issue. Sites login to APIML to obtain a token, which is then used to authenticate all future requests to services through API-ML. The API-ML token is typically stored in a base profile so that connections to all services are done through API-ML with its token. When a new service is brought on-line at a site, it is common for that service to not be immediately integrated with APIML. For at least a period of time, the site makes a direct connection to that service. The site adds user/password properties to that service's profile to authenticate that direct connection. Once again, both user & password and a token are available when Zowe attempts to connect to the service for that profile. In this case, the user & password are the right choice for this service. This is the opposite choice from the previous example. + +As these examples demonstrate, Zowe cannot simply change which authentication type should be given preference. It varies based on what a site is trying to do. That order might also change from one part of the customer's configuration to another. The preferred order in which credentials are chosen is further complicated when we consider that certificates may also be used by a site for some of its services. + +## General approach for a solution + +In this section we identify the key features that a solution would have to provide. + +- The order in which different types of authentication are used should be controlled by the user in the Zowe client configuration. + +- The user must be able to change that authentication order for different parts of the Zowe client configuration. + +- Zowe client logic must be enhanced to select the right authentication type for a profile being used to make a connection. + +- Zowe client extenders (CLI plugins and ZE extensions) should **not** be able to alter the order of authentication types. The user should control that choice. + +## Detailed requirements + +- If a user does not specify the order of authentication, Zowe should use the historical order of authentication so that we do not introduce a breaking change. + +- Zowe has an order of precedence for obtaining property values (config file, environment variable, command line). While a command line option will override the same property stored in a config file, it should not alter the order of authentication. + + - For example, if a user specifies a token value on the command line, it will override a token value stored in a config file. However, + + - If the user has specified that a certificate should be used before a token, and a certificate is also available in the configuration, the certificate should be used because the user configured that certificates are used before tokens. + + - The token should not be used just because it was supplied on the command line. + +- The authentication order only identifies the order in which Zowe chooses the **one** authentication method that will be used. If that first authentication method fails, Zowe will not make a second attempt to authenticate with any of the later authentication methods. + +- Once an auth type is selected, our logic should ensure that only that one auth type is placed into a session object. Thus, logic in down-stream handlers will not alter the order of auth selection, simply by testing for the auth types within the session in a different order than the order that the user specified. + + - If we continue to allow multiple authTypes to be placed into a session, we will have to re-work various functions to test for authType in the desired order. We will also have to provide the object containing that well-defined order to each such function. This will increase the amount of code being changed, and thus increase the probability of mistakes. + +- Zowe clients do not currently support AUTH_TYPE_CERT_PFX, so we cannot add it to a set of available authTypes. If AUTH_TYPE_CERT_PFX is implemented, it should be placed immediately after AUTH_TYPE_CERT_PEM in the default order. + +- Propose that AUTH_TYPE_NONE gets a place in our list of possible authentication types + +- ## Historical behavior + +The objective of this feature is to enable users to define the order in which an authentication type is selected. However, when a user does not specify any such order, the default order should reflect past behavior. + +- The AbstractRestClient currently enforces an order of: + + - AUTH_TYPE_TOKEN + + - AUTH_TYPE_BASIC + + - AUTH_TYPE_BEARER + + - AUTH_TYPE_CERT_PEM + +- All Zowe functions down-stream from AbstractRestClient explicitly override the authentication order from AbstractRestClient to be: + + - AUTH_TYPE_BASIC + + - AUTH_TYPE_BEARER + + - AUTH_TYPE_TOKEN + + - AUTH_TYPE_CERT_PEM + + - Confirm this order + + - Describe how AUTH_TYPE_NONE gets set + +These selections of authentication should be maintained as the default selections for their respective classes to avoid introducing a breaking change. + +## Configuration enhancement + +- authTypeOrder config property +- Levels in config where authType order can reside + +## Functions that are candidates for modification + +The set of candidates for modification consist of all functions that contain the string ***"AUTH_TYPE_"***. This section contains an assessment of whether each such function affects the authentication order. Based on this analysis, those functions that warrant modification are identified in the "Proposed software modifications" section of this document. + +- cli\src\config\auto-init\ApimlAutoInitHandler + + - doAutoInit - This function logins into APIML with the session object if either user & password or cert are in the session object. doAutoInit does not make a selection of order. It lets Login.apimlLogin() make that decision. If only the selected authType is placed into a session, + - **Modify doAutoInit ? No** + +- core\src\rest\ZosmfRestClient.ts + + - processError - This function just alters error message text based on auth types found in the session. If only the selected authType is placed into a session, + - **Modify processError ? No** + +- imperative\src\config\src\ConfigAutoStore.ts + + - _fetchTokenForSessCfg - Since this function is used to explicitly retrieve a token value to be auto-stored into a session config, its use of AUTH_TYPE_TOKEN does not affect the auth order. So, + - **Modify _fetchTokenForSessCfg ? No** + +- imperative\src\imperative\src\config\cmd\import\import.handler.ts + + - buildSession - This function is used to import a config from a URL. That URL is an arbitrary location at a customer site where a config file is kept. It is not the target of a REST request to a mainframe service. By design, the only auth type that it will use is user & password. Supporting more authentication types in the 'import' command is beyond the scoope of this authentication-order feature. Therefore, + - **Modify buildSession ? No** + +- imperative\src\rest\src\client\AbstractRestClient.ts + + This class is the only class to use the recently created ISession.authTypeOrder property, which is an arry of authentication types supplied in the order in which they should be selected. + + - buildOptions - This function tests for the authType based on the order in which they occur in ISession.authTypeOrder. Therefore, + + - **Modify buildOptions ? No** + + - constructor - This function hard-codes the order of authentication types into the ISession.authTypeOrder array. We must create a means to provide the customer-defined order to this function. This function should only use its hard-coded order (as the default order) if a customers does not specify an order. + + - That default order should be: + + - AUTH_TYPE_TOKEN + + - AUTH_TYPE_BASIC + + - AUTH_TYPE_BEARER + + - AUTH_TYPE_CERT_PEM + + - AUTH_TYPE_CERT_PFX + + - AUTH_TYPE_NONE + + - Confirm this order + + - **Modify constructor? yes** + + - Each of the following functions reference AUTH_TYPE_ to a place an identified type into the ISession.type property. Since buildOptions calls just one of the following functions based on being the first available authType in the ISession.authTypeOrder array, none of these functions need to change. + + - **Modify setBearerAuth ? No** + + - **Modify setCertPemAuth ? No** + + - **Modify setPasswordAuth ? No** + + - **Modify setTokenAuth ? No** + +- imperative\src\rest\src\session\AbstractSession.ts + + - buildSession - This function accepts a session. It already confirms that a valid authType has already been set in the session. It then populates some session properties based on the authType that it finds. Other new logic, which ensures that only the selected authType is placed into a session, should have no adverse affect on this function. So, + + - **Modify buildSession ? No** + + - DEFAULT_TYPE - This simply a constant definition set to AUTH_TYPE_NONE. It is not used in any CLI or ZE code outside of this AbstractSession class. Because it is a public property, it cannot be removed without risk of breaking change. If AUTH_TYPE_NONE is added to the ISession.authTypeOrder array, DEFAULT_TYPE should be deprecated, so + + - **Modify DEFAULT_TYPE ? Yes** + +- imperative\src\rest\src\session\ConnectionPropsForSessCfg.ts + + - addPropsOrPrompt + + - resolveSessCfgProps + + - setTypeForTokenRequest + +- imperative\src\rest\src\session\SessConstants.ts + + - Constants and type definitions + +- imperative\src\rest\src\session\Session.ts + + - createFromUrl + +- imperative\src\rest\src\session\doc\IOptionsForAddConnProps.ts + + - supportedAuthTypes + +- imperative\src\rest\src\session\doc\ISession.ts + + - type + + - authTypeOrder + + - Could be the focus of our refactoring, but currently it is only used in + AbstractRestClient.constructor & AbstractRestClient.buildOptions + +- packages\zosuss\src\SshBaseHandler.ts + + - process + +## New software logic to add + +- Describe new functions that must be written to get the authTypeOrder + +- API functions allow programs to specify the auth options that they want. How can this be refactored in a non-breaking way? + +## Proposed deprecations + +Remove this section? + +imperative\src\rest\src\session\AbstractSession.ts: DEFAULT_TYPE \ No newline at end of file From 07197300804495ca6094edd637e853b4cc375da3 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Tue, 15 Oct 2024 13:20:54 -0400 Subject: [PATCH 02/61] Committing local updates before merge from master Signed-off-by: Gene Johnston --- docs/Design_for_selecting_auth_type.md | 179 +++++++++++++++++-------- 1 file changed, 122 insertions(+), 57 deletions(-) diff --git a/docs/Design_for_selecting_auth_type.md b/docs/Design_for_selecting_auth_type.md index 4ee6158433..ef66c9e3d3 100644 --- a/docs/Design_for_selecting_auth_type.md +++ b/docs/Design_for_selecting_auth_type.md @@ -40,11 +40,15 @@ In this section we identify the key features that a solution would have to provi - Once an auth type is selected, our logic should ensure that only that one auth type is placed into a session object. Thus, logic in down-stream handlers will not alter the order of auth selection, simply by testing for the auth types within the session in a different order than the order that the user specified. - - If we continue to allow multiple authTypes to be placed into a session, we will have to re-work various functions to test for authType in the desired order. We will also have to provide the object containing that well-defined order to each such function. This will increase the amount of code being changed, and thus increase the probability of mistakes. + - If we continue to allow multiple auth types to be placed into a session, we will have to re-work various functions to test for auth type in the desired order. We will also have to provide the object containing that well-defined order to each such function. This will increase the amount of code being changed, and thus increase the probability of mistakes. -- Zowe clients do not currently support AUTH_TYPE_CERT_PFX, so we cannot add it to a set of available authTypes. If AUTH_TYPE_CERT_PFX is implemented, it should be placed immediately after AUTH_TYPE_CERT_PEM in the default order. +- Zowe clients do not currently support AUTH_TYPE_CERT_PFX, so we cannot add it to a set of available auth types. If AUTH_TYPE_CERT_PFX is implemented, it should be placed immediately after AUTH_TYPE_CERT_PEM in the default order. -- Propose that AUTH_TYPE_NONE gets a place in our list of possible authentication types +- Customers should be able to specify AUTH_TYPE_NONE in their preferred order of auth types. While it is not advisable to have no authentication, if a customer has a service that requires no authentication, the customer should be able to specify AUTH_TYPE_NONE at the top of their list of auth types applicable to that particular profile. + +- A customer should not have to specify every possible auth type in their ordered list of auth types. If a site only uses password and tokens, the customer should be able to specify only those two auth types in their list. + +- A customer-specified list of auth types must contain at least one of our supported auth types. - ## Historical behavior @@ -60,7 +64,7 @@ The objective of this feature is to enable users to define the order in which an - AUTH_TYPE_CERT_PEM -- All Zowe functions down-stream from AbstractRestClient explicitly override the authentication order from AbstractRestClient to be: +- Zowe classes other than AbstractRestClient (like AbstractSession) currently override the authentication order from AbstractRestClient into: - AUTH_TYPE_BASIC @@ -69,71 +73,54 @@ The objective of this feature is to enable users to define the order in which an - AUTH_TYPE_TOKEN - AUTH_TYPE_CERT_PEM - - - Confirm this order - - - Describe how AUTH_TYPE_NONE gets set These selections of authentication should be maintained as the default selections for their respective classes to avoid introducing a breaking change. ## Configuration enhancement - authTypeOrder config property -- Levels in config where authType order can reside +- Levels in config where auth type order can reside + - Base + - Nested parent + - Individual profile -## Functions that are candidates for modification +## Determination of functions to be modified The set of candidates for modification consist of all functions that contain the string ***"AUTH_TYPE_"***. This section contains an assessment of whether each such function affects the authentication order. Based on this analysis, those functions that warrant modification are identified in the "Proposed software modifications" section of this document. - cli\src\config\auto-init\ApimlAutoInitHandler - - doAutoInit - This function logins into APIML with the session object if either user & password or cert are in the session object. doAutoInit does not make a selection of order. It lets Login.apimlLogin() make that decision. If only the selected authType is placed into a session, + - doAutoInit - This function logins into APIML with the session object if either user & password or cert are in the session object. doAutoInit does not make a selection of order. It lets Login.apimlLogin() make that decision. If only the selected auth type is placed into a session, then no need to change. - **Modify doAutoInit ? No** - core\src\rest\ZosmfRestClient.ts - - processError - This function just alters error message text based on auth types found in the session. If only the selected authType is placed into a session, + - processError - This function just alters error message text based on auth types found in the session. If only the selected auth type is placed into a session, then no need to change. - **Modify processError ? No** - imperative\src\config\src\ConfigAutoStore.ts - - _fetchTokenForSessCfg - Since this function is used to explicitly retrieve a token value to be auto-stored into a session config, its use of AUTH_TYPE_TOKEN does not affect the auth order. So, + - _fetchTokenForSessCfg - Since this function is used to explicitly retrieve a token value to be auto-stored into a session config, its use of AUTH_TYPE_TOKEN does not affect the auth order. So, no need to change. - **Modify _fetchTokenForSessCfg ? No** - imperative\src\imperative\src\config\cmd\import\import.handler.ts - - buildSession - This function is used to import a config from a URL. That URL is an arbitrary location at a customer site where a config file is kept. It is not the target of a REST request to a mainframe service. By design, the only auth type that it will use is user & password. Supporting more authentication types in the 'import' command is beyond the scoope of this authentication-order feature. Therefore, + - buildSession - This function is used to import a config from a URL. That URL is an arbitrary location at a customer site where a config file is kept. It is not the target of a REST request to a mainframe service. By design, the only auth type that it will use is user & password. Supporting more authentication types in the 'import' command is beyond the scope of this authentication-order feature. Therefore, no need to change. - **Modify buildSession ? No** - imperative\src\rest\src\client\AbstractRestClient.ts - This class is the only class to use the recently created ISession.authTypeOrder property, which is an arry of authentication types supplied in the order in which they should be selected. + This class is the only class to use the recently created ISession.authTypeOrder property, which is an array of authentication types supplied in the order in which they should be selected. - - buildOptions - This function tests for the authType based on the order in which they occur in ISession.authTypeOrder. Therefore, + - buildOptions - This function tests for the auth type based on the order in which they occur in ISession.authTypeOrder. Therefore, no need to change. - **Modify buildOptions ? No** - - constructor - This function hard-codes the order of authentication types into the ISession.authTypeOrder array. We must create a means to provide the customer-defined order to this function. This function should only use its hard-coded order (as the default order) if a customers does not specify an order. - - - That default order should be: - - - AUTH_TYPE_TOKEN - - - AUTH_TYPE_BASIC - - - AUTH_TYPE_BEARER - - - AUTH_TYPE_CERT_PEM - - - AUTH_TYPE_CERT_PFX - - - AUTH_TYPE_NONE - - - Confirm this order + - constructor - This function currently hard-codes an order of authentication types into the ISession.authTypeOrder array. We must create a means to record the customer-defined order in this function. This function should call a common function (tentatively named recordAuthTypeOrderFromConfig) to do this work. recordAuthTypeOrderFromConfig should be able to set the old hard-coded order (as the default order) only if a customer does not specify an order. - **Modify constructor? yes** - - Each of the following functions reference AUTH_TYPE_ to a place an identified type into the ISession.type property. Since buildOptions calls just one of the following functions based on being the first available authType in the ISession.authTypeOrder array, none of these functions need to change. + - Each of the following functions reference AUTH_TYPE_XXX to a place an identified type into the ISession.type property. Since buildOptions calls just one of the following functions based on being the first available auth type in the ISession.authTypeOrder array, none of these functions need to change. - **Modify setBearerAuth ? No** @@ -145,55 +132,133 @@ The set of candidates for modification consist of all functions that contain the - imperative\src\rest\src\session\AbstractSession.ts - - buildSession - This function accepts a session. It already confirms that a valid authType has already been set in the session. It then populates some session properties based on the authType that it finds. Other new logic, which ensures that only the selected authType is placed into a session, should have no adverse affect on this function. So, + - buildSession - This private function is called by the constructor, which accepts an Isession object. A caller could populate multiple auth types (and related properties) into that supplied session. Session.buildSession() will have to scrub all but the highest priority available auth type from the session. We should create a common utility function (tentatively named selectTopAuthType) to do the scrubbing. selectTopAuthType can be also be called from ConnectionPropsForSessCfg.resolveSessCfgProps function as described below. - - **Modify buildSession ? No** + - **Modify buildSession ? Yes** - - DEFAULT_TYPE - This simply a constant definition set to AUTH_TYPE_NONE. It is not used in any CLI or ZE code outside of this AbstractSession class. Because it is a public property, it cannot be removed without risk of breaking change. If AUTH_TYPE_NONE is added to the ISession.authTypeOrder array, DEFAULT_TYPE should be deprecated, so + - DEFAULT_TYPE - This simply a constant definition set to AUTH_TYPE_NONE. It is not used in any CLI or ZE code outside of this AbstractSession class. Because it is a public property, it cannot be removed without risk of breaking change. If AUTH_TYPE_NONE is added to the ISession.authTypeOrder array, DEFAULT_TYPE should be deprecated. - **Modify DEFAULT_TYPE ? Yes** - imperative\src\rest\src\session\ConnectionPropsForSessCfg.ts - - addPropsOrPrompt + - addPropsOrPrompt - This function only uses AUTH_TYPE_XXX to determine whether a token and a cert are irrelevant based on the existence of AUTH_TYPE_TOKEN. Those items should not need to change. However, addPropsOrPrompt accepts three parameters, each of which can have property overrides of auth type. After calling resolveSessCfgProps, addPropsOrPrompt continues to modify the session properties with values from its parameters. Thus addPropsOrPrompt must be refactored to work properly with a refactored resolveSessCfgProps. + + - **Modify addPropsOrPrompt ? Yes** - - resolveSessCfgProps + - resolveSessCfgProps - Many functions call this function before creating a new session. This function could scrub all but the selected auth type and related properties from the session object. However, callers could call 'new Session()' without first calling resolveSessCfgProps(). Thus, Session.buildSession() will have to perform the same scrubbing of auth types from the session. Both Session.buildSession and resolveSessCfgProps should call selectTopAuthType() to do the scrubbing. + + - **Modify resolveSessCfgProps ? Yes** - - setTypeForTokenRequest + - setTypeForTokenRequest - This function handles setting auth type to AUTH_TYPE_TOKEN to get a token back from user & password. This does not appear to require any change, but it should be revisited after resolveSessCfgProps is refactored. + + - **Modify setTypeForTokenRequest ? Maybe** - imperative\src\rest\src\session\SessConstants.ts - - Constants and type definitions + - Constants and type definitions of AUTH_TYPE_XXX are what they need to be. + - **Modify constants ? No** - imperative\src\rest\src\session\Session.ts - - createFromUrl + - createFromUrl - This function is only called from ImportHandler.buildSession when to enable importing a config from a URL. As with ImportHandler.buildSession, the use of AUTH_TYPE_BASIC when user & password exist is appropriate and should not need to change. + - **Modify createFromUrl ? No** - imperative\src\rest\src\session\doc\IOptionsForAddConnProps.ts - - supportedAuthTypes + - supportedAuthTypes - Our set of supported auth types will not change as part of this feature. + - **Modify supportedAuthTypes ? No** - imperative\src\rest\src\session\doc\ISession.ts - - type - - - authTypeOrder + - authTypeOrder - This property could be the focus of our refactoring, but currently it is hard-coded and only used in AbstractRestClient.constructor & AbstractRestClient.buildOptions. This property should be used to hold the customer-defined order of authentication types. There is no reason to change this property. Other code will repopulate authTypeOrder's set of values based on customer input. It is possible that an ISession may not be available at the time we want to store the customer-defined order of authentication types. Another object may need to store that order, which is later transferred into this ISession property. - - Could be the focus of our refactoring, but currently it is only used in - AbstractRestClient.constructor & AbstractRestClient.buildOptions + - **Modify authTypeOrder ? No** - packages\zosuss\src\SshBaseHandler.ts - - process + - process - Since our SSH connection can only use basic authentication, this function's use of AUTH_TYPE_BASIC is appropriate and does not need to change. + - **Modify process ? No** ## New software logic to add -- Describe new functions that must be written to get the authTypeOrder - -- API functions allow programs to specify the auth options that they want. How can this be refactored in a non-breaking way? - -## Proposed deprecations +This section describes new functions that must be added to achieve the desired functionality. -Remove this section? - -imperative\src\rest\src\session\AbstractSession.ts: DEFAULT_TYPE \ No newline at end of file +- Utility function to record the order of authentication types. + + > --- + > + > @internal + > + > public UnknownClass.recordAuthTypeOrderFromConfig(tokenIsTopDefault: boolean = false): string[ ] { + > + > - This function should obtain the customer-defined authentication order from the Zowe client config file. + > + > - It must confirm that the customer specified valid values. If not, it should record the error, and fall-back to the appropriate default order. + > + > - It should place those auth types into a string array that is returned. + > + > - Maybe instead of returning that array, the array is set into come commonly accessible object (like ImperativeConfig)? + > + > - If no order has been configured into zowe.config.json, it should create a default order to be backward compatible. + > + > - If tokenIsTopDefault is true, it should place token at the top of the order, resulting in this order: + > + > - AUTH_TYPE_TOKEN + > + > - AUTH_TYPE_BASIC + > + > - AUTH_TYPE_BEARER + > + > - AUTH_TYPE_CERT_PEM + > + > - AUTH_TYPE_CERT_PFX + > + > - AUTH_TYPE_NONE + > + > - If tokenIsTopDefault is false, it should place basic at the top of the order, resulting in this order: + > + > - AUTH_TYPE_BASIC + > + > - AUTH_TYPE_TOKEN + > + > -  AUTH_TYPE_BEARER + > + > - AUTH_TYPE_CERT_PEM + > + > - AUTH_TYPE_CERT_PFX + > + > - AUTH_TYPE_NONE + > + > } + +- Utility function to get the array of authentication types. + + > --- + > + > public UnknownClass.getAuthTypeOrder(): string[ ] { + > + > - This function should return the recorded array of authentication types. They will be in the order of top preference first. + > + > - Maybe this function lives in ImperativeConfig?. + > + > } + +- Utility function to select the top available authentication type in a session. + + > --- + > + > @internal + > + > public UnknownClass.selectTopAuthType(iSessObj: ISession): void { + > + > - This function should use the new getAuthTypeOrder function to get the ordered array of auth types. + > - It should confirm if the auth types (in the preferred order) and their associated properties are available in the iSessObj. + > - Once the first auth type is found, the properties related to all other auth types should be removed from iSessObj. + > - Maybe this function lives in AbstractSession?. + > + > } + + + +# \ No newline at end of file From 4f85c56050ef25223feb7e9cf32d7d999cfbf0a0 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Tue, 12 Nov 2024 14:52:26 -0500 Subject: [PATCH 03/61] Add Doc Impact Signed-off-by: Gene Johnston --- docs/Design_for_selecting_auth_type.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/Design_for_selecting_auth_type.md b/docs/Design_for_selecting_auth_type.md index ef66c9e3d3..9292693215 100644 --- a/docs/Design_for_selecting_auth_type.md +++ b/docs/Design_for_selecting_auth_type.md @@ -83,6 +83,17 @@ These selections of authentication should be maintained as the default selection - Base - Nested parent - Individual profile + - As a sibling of the secure array. + +## Documentation Impact + +- We must describe the purpose and function of the new authOrder property. + +- We must describe where users can place the authOrder property. + +- We must describe the default order of authentication, when no authOrder property is supplied. + +- We must notify extenders to guide their customers to supply an appropriate authOrder property if their extension needs a non-default order. ## Determination of functions to be modified @@ -180,7 +191,7 @@ The set of candidates for modification consist of all functions that contain the - process - Since our SSH connection can only use basic authentication, this function's use of AUTH_TYPE_BASIC is appropriate and does not need to change. - **Modify process ? No** -## New software logic to add +## New software logic that must be added This section describes new functions that must be added to achieve the desired functionality. @@ -259,6 +270,4 @@ This section describes new functions that must be added to achieve the desired f > > } - - # \ No newline at end of file From f953ab837564e5a600af1919d0bb5df67748e642 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Tue, 12 Nov 2024 18:04:54 -0500 Subject: [PATCH 04/61] Complete section "configuration enhancement" Signed-off-by: Gene Johnston --- docs/Design_for_selecting_auth_type.md | 118 +++++++++++++++++-------- 1 file changed, 81 insertions(+), 37 deletions(-) diff --git a/docs/Design_for_selecting_auth_type.md b/docs/Design_for_selecting_auth_type.md index 9292693215..b828393dc6 100644 --- a/docs/Design_for_selecting_auth_type.md +++ b/docs/Design_for_selecting_auth_type.md @@ -20,7 +20,7 @@ In this section we identify the key features that a solution would have to provi - The user must be able to change that authentication order for different parts of the Zowe client configuration. -- Zowe client logic must be enhanced to select the right authentication type for a profile being used to make a connection. +- Zowe client logic must be enhanced to select the authentication type for a profile used to make a connection based on a user-specified preferred order. - Zowe client extenders (CLI plugins and ZE extensions) should **not** be able to alter the order of authentication types. The user should control that choice. @@ -32,25 +32,25 @@ In this section we identify the key features that a solution would have to provi - For example, if a user specifies a token value on the command line, it will override a token value stored in a config file. However, - - If the user has specified that a certificate should be used before a token, and a certificate is also available in the configuration, the certificate should be used because the user configured that certificates are used before tokens. + - If the user has specified that a certificate should be used before a token, and a certificate is also available in the configuration, the certificate should be used because the user configured that certificates should be used before tokens. - The token should not be used just because it was supplied on the command line. - The authentication order only identifies the order in which Zowe chooses the **one** authentication method that will be used. If that first authentication method fails, Zowe will not make a second attempt to authenticate with any of the later authentication methods. -- Once an auth type is selected, our logic should ensure that only that one auth type is placed into a session object. Thus, logic in down-stream handlers will not alter the order of auth selection, simply by testing for the auth types within the session in a different order than the order that the user specified. +- Once an authentication is selected, our logic should ensure that only that one type of authentication is placed into a session object. Thus, logic in down-stream handlers will not alter the order of authentication selection, simply by testing for the authentications within the session in a different order than the order that the user specified. - - If we continue to allow multiple auth types to be placed into a session, we will have to re-work various functions to test for auth type in the desired order. We will also have to provide the object containing that well-defined order to each such function. This will increase the amount of code being changed, and thus increase the probability of mistakes. + - If we were to continue to allow multiple authentications to be placed into a session, we will have to re-work various functions to test for authentications in the desired order. We will also have to provide the object containing that well-defined order to each such function. This will increase the amount of code being changed, and thus increase the probability of mistakes. -- Zowe clients do not currently support AUTH_TYPE_CERT_PFX, so we cannot add it to a set of available auth types. If AUTH_TYPE_CERT_PFX is implemented, it should be placed immediately after AUTH_TYPE_CERT_PEM in the default order. +- Zowe clients do not currently support AUTH_TYPE_CERT_PFX, so we cannot add it to a set of available authentications. If AUTH_TYPE_CERT_PFX is implemented, it should be placed immediately after AUTH_TYPE_CERT_PEM in the default order. -- Customers should be able to specify AUTH_TYPE_NONE in their preferred order of auth types. While it is not advisable to have no authentication, if a customer has a service that requires no authentication, the customer should be able to specify AUTH_TYPE_NONE at the top of their list of auth types applicable to that particular profile. +- Customers should be able to specify AUTH_TYPE_NONE in their preferred order of authentications. While it is not advisable to have no authentication, if a customer has a service that requires no authentication, the customer should be able to specify AUTH_TYPE_NONE at the top of their list of authentications applicable to that particular profile. -- A customer should not have to specify every possible auth type in their ordered list of auth types. If a site only uses password and tokens, the customer should be able to specify only those two auth types in their list. +- A customer should not have to specify every possible authentication in their ordered list of authentications. If a site only uses password and tokens, the customer should be able to specify only those two authentications in their list. -- A customer-specified list of auth types must contain at least one of our supported auth types. +- A customer-specified list of authentications must contain at least one of our supported authentications. -- ## Historical behavior +## Historical behavior The objective of this feature is to enable users to define the order in which an authentication type is selected. However, when a user does not specify any such order, the default order should reflect past behavior. @@ -78,12 +78,56 @@ These selections of authentication should be maintained as the default selection ## Configuration enhancement -- authTypeOrder config property -- Levels in config where auth type order can reside - - Base - - Nested parent - - Individual profile - - As a sibling of the secure array. +A new profile property named **authOrder** should be created to enable users to specify their order of precedence for the authentication to be used when making a REST connection. The authOrder property should be treated like one of our key connection properties (like host and port). Thus authOrder would have the following characteristics: + +- It must be specified within a "properties" object. That "properties" object could reside in: + + - A base profile + + - A parent profile of a nested configuration. + + - Any profile of type **zosmf**. + + - Any profile specific to a plugin (or VSCode extension) that supports a REST connection. For example an **endevor** profile could contain an **authOrder** property, but an **endevor-location** profile would not. + +- Our existing inheritance of connection properties should also apply to the inheritance of the authOrder property. + +- We should be able to use our logic for where and how the **rejectUnauthorized** property is handled as a model for how we handle the **authOrder** property. + +For example, the user could specify their desired authOrder like this: + +``` +"properties": { +    "host": ... , +    "port": ... , +    "rejectUnauthorized": ... , +    "authOrder": [ "basic", "token", "cert-pem"] +} +``` + +The programmatic definition of authOrder would be: + +``` +authOrder[SessConstants.AUTH_TYPE_CHOICES]    +``` + +The current set of AUTH_TYPE_CHOICES are: + +- AUTH_TYPE_BASIC = "basic" + +- AUTH_TYPE_BEARER = "bearer" + +- AUTH_TYPE_TOKEN = "token" + +- AUTH_TYPE_CERT_PEM = "cert-pem" + +- AUTH_TYPE_NONE = "none" + +We should add a new AUTH_TYPE_CHOICE of: + +- AUTH_TYPE_SSH_KEY = "ssh-key" + +That addition would enable customers to also specify the authentication order of precedence for an SSH connection using an authOrder property. The only permissible values for an ssh connection would be "basic" and "ssh-key". Our ssh-handling logic will have to be modified to enforce that restriction and to honor the order. Conversely, our zosmf-handling logic would have to be modified to reject "ssh-key" in authOrder (or at least ignore it). If we choose not to implement authOrder for ssh at this time, we should at least create a design and implementation that can tolerate the addition of "ssh-key" at a later date. ## Documentation Impact @@ -97,16 +141,16 @@ These selections of authentication should be maintained as the default selection ## Determination of functions to be modified -The set of candidates for modification consist of all functions that contain the string ***"AUTH_TYPE_"***. This section contains an assessment of whether each such function affects the authentication order. Based on this analysis, those functions that warrant modification are identified in the "Proposed software modifications" section of this document. +The set of candidates for modification consist of all functions that contain the string ***"AUTH_TYPE_"***. This section contains an assessment of whether each such function affects the authentication order and must be modified. - cli\src\config\auto-init\ApimlAutoInitHandler - - doAutoInit - This function logins into APIML with the session object if either user & password or cert are in the session object. doAutoInit does not make a selection of order. It lets Login.apimlLogin() make that decision. If only the selected auth type is placed into a session, then no need to change. + - doAutoInit - This function logins into APIML with the session object if either user & password or cert are in the session object. doAutoInit does not make a selection of order. It lets Login.apimlLogin() make that decision. If only the selected authentication is placed into a session, then no need to change. - **Modify doAutoInit ? No** - core\src\rest\ZosmfRestClient.ts - - processError - This function just alters error message text based on auth types found in the session. If only the selected auth type is placed into a session, then no need to change. + - processError - This function just alters error message text based on authentications found in the session. If only the selected authentication is placed into a session, then no need to change. - **Modify processError ? No** - imperative\src\config\src\ConfigAutoStore.ts @@ -116,22 +160,22 @@ The set of candidates for modification consist of all functions that contain the - imperative\src\imperative\src\config\cmd\import\import.handler.ts - - buildSession - This function is used to import a config from a URL. That URL is an arbitrary location at a customer site where a config file is kept. It is not the target of a REST request to a mainframe service. By design, the only auth type that it will use is user & password. Supporting more authentication types in the 'import' command is beyond the scope of this authentication-order feature. Therefore, no need to change. + - buildSession - This function is used to import a config from a URL. That URL is an arbitrary location at a customer site where a config file is kept. It is not the target of a REST request to a mainframe service. By design, the only authentication that it will use is user & password. Supporting more authentication types in the 'import' command is beyond the scope of this authentication-order feature. Therefore, no need to change. - **Modify buildSession ? No** - imperative\src\rest\src\client\AbstractRestClient.ts This class is the only class to use the recently created ISession.authTypeOrder property, which is an array of authentication types supplied in the order in which they should be selected. - - buildOptions - This function tests for the auth type based on the order in which they occur in ISession.authTypeOrder. Therefore, no need to change. + - buildOptions - This function tests for the authentication based on the order in which they occur in ISession.authTypeOrder. Therefore, no need to change. - **Modify buildOptions ? No** - - constructor - This function currently hard-codes an order of authentication types into the ISession.authTypeOrder array. We must create a means to record the customer-defined order in this function. This function should call a common function (tentatively named recordAuthTypeOrderFromConfig) to do this work. recordAuthTypeOrderFromConfig should be able to set the old hard-coded order (as the default order) only if a customer does not specify an order. + - constructor - This function currently hard-codes an order of authentication types into the ISession.authTypeOrder array. We must create a means to record the customer-defined order in this function. This function should call a common function (tentatively named recordAuthOrderFromConfig) to do this work. recordAuthOrderFromConfig should be able to set the old hard-coded order (as the default order) only if a customer does not specify an order. - **Modify constructor? yes** - - Each of the following functions reference AUTH_TYPE_XXX to a place an identified type into the ISession.type property. Since buildOptions calls just one of the following functions based on being the first available auth type in the ISession.authTypeOrder array, none of these functions need to change. + - Each of the following functions reference AUTH_TYPE_XXX to a place an identified type into the ISession.type property. Since buildOptions calls just one of the following functions based on being the first available authentication in the ISession.authTypeOrder array, none of these functions need to change. - **Modify setBearerAuth ? No** @@ -143,7 +187,7 @@ The set of candidates for modification consist of all functions that contain the - imperative\src\rest\src\session\AbstractSession.ts - - buildSession - This private function is called by the constructor, which accepts an Isession object. A caller could populate multiple auth types (and related properties) into that supplied session. Session.buildSession() will have to scrub all but the highest priority available auth type from the session. We should create a common utility function (tentatively named selectTopAuthType) to do the scrubbing. selectTopAuthType can be also be called from ConnectionPropsForSessCfg.resolveSessCfgProps function as described below. + - buildSession - This private function is called by the constructor, which accepts an Isession object. A caller could populate multiple authentications (and related properties) into that supplied session. Session.buildSession() will have to scrub all but the highest priority available authentication from the session. We should create a common utility function (tentatively named selectTopAuthType) to do the scrubbing. selectTopAuthType can be also be called from ConnectionPropsForSessCfg.resolveSessCfgProps function as described below. - **Modify buildSession ? Yes** @@ -153,15 +197,15 @@ The set of candidates for modification consist of all functions that contain the - imperative\src\rest\src\session\ConnectionPropsForSessCfg.ts - - addPropsOrPrompt - This function only uses AUTH_TYPE_XXX to determine whether a token and a cert are irrelevant based on the existence of AUTH_TYPE_TOKEN. Those items should not need to change. However, addPropsOrPrompt accepts three parameters, each of which can have property overrides of auth type. After calling resolveSessCfgProps, addPropsOrPrompt continues to modify the session properties with values from its parameters. Thus addPropsOrPrompt must be refactored to work properly with a refactored resolveSessCfgProps. + - addPropsOrPrompt - This function only uses AUTH_TYPE_XXX to determine whether a token and a cert are irrelevant based on the existence of AUTH_TYPE_TOKEN. Those items should not need to change. However, addPropsOrPrompt accepts three parameters, each of which can have property overrides of authentication. After calling resolveSessCfgProps, addPropsOrPrompt continues to modify the session properties with values from its parameters. Thus addPropsOrPrompt must be refactored to work properly with a refactored resolveSessCfgProps. - **Modify addPropsOrPrompt ? Yes** - - resolveSessCfgProps - Many functions call this function before creating a new session. This function could scrub all but the selected auth type and related properties from the session object. However, callers could call 'new Session()' without first calling resolveSessCfgProps(). Thus, Session.buildSession() will have to perform the same scrubbing of auth types from the session. Both Session.buildSession and resolveSessCfgProps should call selectTopAuthType() to do the scrubbing. + - resolveSessCfgProps - Many functions call this function before creating a new session. This function could scrub all but the selected authentication and related properties from the session object. However, callers could call 'new Session()' without first calling resolveSessCfgProps(). Thus, Session.buildSession() will have to perform the same scrubbing of authentications from the session. Both Session.buildSession and resolveSessCfgProps should call selectTopAuthType() to do the scrubbing. - **Modify resolveSessCfgProps ? Yes** - - setTypeForTokenRequest - This function handles setting auth type to AUTH_TYPE_TOKEN to get a token back from user & password. This does not appear to require any change, but it should be revisited after resolveSessCfgProps is refactored. + - setTypeForTokenRequest - This function handles setting authentication to AUTH_TYPE_TOKEN to get a token back from user & password. This does not appear to require any change, but it should be revisited after resolveSessCfgProps is refactored. - **Modify setTypeForTokenRequest ? Maybe** @@ -177,21 +221,21 @@ The set of candidates for modification consist of all functions that contain the - imperative\src\rest\src\session\doc\IOptionsForAddConnProps.ts - - supportedAuthTypes - Our set of supported auth types will not change as part of this feature. + - supportedAuthTypes - Our set of supported authentications will not change as part of this feature. - **Modify supportedAuthTypes ? No** - imperative\src\rest\src\session\doc\ISession.ts - - authTypeOrder - This property could be the focus of our refactoring, but currently it is hard-coded and only used in AbstractRestClient.constructor & AbstractRestClient.buildOptions. This property should be used to hold the customer-defined order of authentication types. There is no reason to change this property. Other code will repopulate authTypeOrder's set of values based on customer input. It is possible that an ISession may not be available at the time we want to store the customer-defined order of authentication types. Another object may need to store that order, which is later transferred into this ISession property. + - authTypeOrder - This property could be the focus of our refactoring, but currently it is hard-coded and only used in AbstractRestClient.constructor & AbstractRestClient.buildOptions. This property should be used to hold the customer-defined order of authentication types. There is no reason to change this property. Other code will repopulate authTypeOrder's set of values based on customer input. It is possible that an ISession may not be available at the time we want to store the customer-defined order of authentication types. Another object may need to store that order, which is later transferred into this ISession property. The only reason that we may want to change this item is to rename it from authtypeOrder to authOrder to reflect the same, simpler object name that a user will use to specify the authentication order. We should only change the name of authTypeOrder if it is only used internally by Zowe (and thus would be a non-breaking change). - - **Modify authTypeOrder ? No** + - **Modify authTypeOrder ? Maybe** - packages\zosuss\src\SshBaseHandler.ts - process - Since our SSH connection can only use basic authentication, this function's use of AUTH_TYPE_BASIC is appropriate and does not need to change. - **Modify process ? No** -## New software logic that must be added +## New functions that must be added This section describes new functions that must be added to achieve the desired functionality. @@ -201,13 +245,13 @@ This section describes new functions that must be added to achieve the desired f > > @internal > - > public UnknownClass.recordAuthTypeOrderFromConfig(tokenIsTopDefault: boolean = false): string[ ] { + > public UnknownClass.recordAuthOrderFromConfig(tokenIsTopDefault: boolean = false): string[ ] { > - > - This function should obtain the customer-defined authentication order from the Zowe client config file. + > - as siblingThis function should obtain the customer-defined authentication order from the Zowe client config file. > > - It must confirm that the customer specified valid values. If not, it should record the error, and fall-back to the appropriate default order. > - > - It should place those auth types into a string array that is returned. + > - It should place those authentications into a string array that is returned. > > - Maybe instead of returning that array, the array is set into come commonly accessible object (like ImperativeConfig)? > @@ -247,7 +291,7 @@ This section describes new functions that must be added to achieve the desired f > --- > - > public UnknownClass.getAuthTypeOrder(): string[ ] { + > public UnknownClass.getAuthOrder(): string[ ] { > > - This function should return the recorded array of authentication types. They will be in the order of top preference first. > @@ -263,9 +307,9 @@ This section describes new functions that must be added to achieve the desired f > > public UnknownClass.selectTopAuthType(iSessObj: ISession): void { > - > - This function should use the new getAuthTypeOrder function to get the ordered array of auth types. - > - It should confirm if the auth types (in the preferred order) and their associated properties are available in the iSessObj. - > - Once the first auth type is found, the properties related to all other auth types should be removed from iSessObj. + > - This function should use the new getAuthOrder function to get the ordered array of authentications. + > - It should confirm if the authentications (in the preferred order) and their associated properties are available in the iSessObj. + > - Once the first authentication is found, the properties related to all other authentications should be removed from iSessObj. > - Maybe this function lives in AbstractSession?. > > } From d6417f4efeb18abdf7d96ce34dd9faf739614028 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Wed, 13 Nov 2024 18:09:03 -0500 Subject: [PATCH 05/61] Add ssh functions to list of functions to be modified Signed-off-by: Gene Johnston --- docs/Design_for_selecting_auth_type.md | 29 +++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/docs/Design_for_selecting_auth_type.md b/docs/Design_for_selecting_auth_type.md index b828393dc6..fbf2134e2f 100644 --- a/docs/Design_for_selecting_auth_type.md +++ b/docs/Design_for_selecting_auth_type.md @@ -93,8 +93,10 @@ A new profile property named **authOrder** should be created to enable users to - Our existing inheritance of connection properties should also apply to the inheritance of the authOrder property. - We should be able to use our logic for where and how the **rejectUnauthorized** property is handled as a model for how we handle the **authOrder** property. + + - One difference from **rejectUnauthorized** is that for **authOrder** we should accept its value from a zowe.config.json file, but not from a command line argument or environment variable. Because **authOrder** is an array, it will be difficult and error-prone for users to correctly specify **authOrder** on a command line or in an environment variable. -For example, the user could specify their desired authOrder like this: +As an example, the user could specify their desired authOrder like this: ``` "properties": { @@ -141,7 +143,7 @@ That addition would enable customers to also specify the authentication order of ## Determination of functions to be modified -The set of candidates for modification consist of all functions that contain the string ***"AUTH_TYPE_"***. This section contains an assessment of whether each such function affects the authentication order and must be modified. +The set of candidates for modification consist of all functions that contain the string ***"AUTH_TYPE_"***. This section contains an assessment of whether each such function affects the authentication order and must be modified. - cli\src\config\auto-init\ApimlAutoInitHandler @@ -171,7 +173,7 @@ The set of candidates for modification consist of all functions that contain the - **Modify buildOptions ? No** - - constructor - This function currently hard-codes an order of authentication types into the ISession.authTypeOrder array. We must create a means to record the customer-defined order in this function. This function should call a common function (tentatively named recordAuthOrderFromConfig) to do this work. recordAuthOrderFromConfig should be able to set the old hard-coded order (as the default order) only if a customer does not specify an order. + - constructor - This function currently hard-codes an order of authentication types into the ISession.authTypeOrder array. We must create a means to record the customer-defined order in this function. This function should call a common function (tentatively named recordAuthOrderFromConfig) to do this work. recordAuthOrderFromConfig should be able to set the old hard-coded order (as the default order) only if a customer does not specify an order. - **Modify constructor? yes** @@ -187,7 +189,7 @@ The set of candidates for modification consist of all functions that contain the - imperative\src\rest\src\session\AbstractSession.ts - - buildSession - This private function is called by the constructor, which accepts an Isession object. A caller could populate multiple authentications (and related properties) into that supplied session. Session.buildSession() will have to scrub all but the highest priority available authentication from the session. We should create a common utility function (tentatively named selectTopAuthType) to do the scrubbing. selectTopAuthType can be also be called from ConnectionPropsForSessCfg.resolveSessCfgProps function as described below. + - buildSession - This private function is called by the constructor, which accepts an Isession object. A caller could populate multiple authentications (and related properties) into that supplied session. Session.buildSession() will have to scrub all but the highest priority available authentication from the session. We should create a common utility function (tentatively named selectPreferredAuth) to do the scrubbing. selectPreferredAuth can be also be called from ConnectionPropsForSessCfg.resolveSessCfgProps function as described below. - **Modify buildSession ? Yes** @@ -201,13 +203,13 @@ The set of candidates for modification consist of all functions that contain the - **Modify addPropsOrPrompt ? Yes** - - resolveSessCfgProps - Many functions call this function before creating a new session. This function could scrub all but the selected authentication and related properties from the session object. However, callers could call 'new Session()' without first calling resolveSessCfgProps(). Thus, Session.buildSession() will have to perform the same scrubbing of authentications from the session. Both Session.buildSession and resolveSessCfgProps should call selectTopAuthType() to do the scrubbing. + - resolveSessCfgProps - Many functions call this function before creating a new session. This function could scrub all but the selected authentication and related properties from the session object. However, callers could call 'new Session()' without first calling resolveSessCfgProps(). Thus, Session.buildSession() will have to perform the same scrubbing of authentications from the session. Both Session.buildSession and resolveSessCfgProps should call selectPreferredAuth() to do the scrubbing. - **Modify resolveSessCfgProps ? Yes** - setTypeForTokenRequest - This function handles setting authentication to AUTH_TYPE_TOKEN to get a token back from user & password. This does not appear to require any change, but it should be revisited after resolveSessCfgProps is refactored. - - **Modify setTypeForTokenRequest ? Maybe** + - **Modify setTypeForTokenRequest ? Maybe** - imperative\src\rest\src\session\SessConstants.ts @@ -228,12 +230,17 @@ The set of candidates for modification consist of all functions that contain the - authTypeOrder - This property could be the focus of our refactoring, but currently it is hard-coded and only used in AbstractRestClient.constructor & AbstractRestClient.buildOptions. This property should be used to hold the customer-defined order of authentication types. There is no reason to change this property. Other code will repopulate authTypeOrder's set of values based on customer input. It is possible that an ISession may not be available at the time we want to store the customer-defined order of authentication types. Another object may need to store that order, which is later transferred into this ISession property. The only reason that we may want to change this item is to rename it from authtypeOrder to authOrder to reflect the same, simpler object name that a user will use to specify the authentication order. We should only change the name of authTypeOrder if it is only used internally by Zowe (and thus would be a non-breaking change). - - **Modify authTypeOrder ? Maybe** + - **Modify authTypeOrder ? Maybe** - packages\zosuss\src\SshBaseHandler.ts - - process - Since our SSH connection can only use basic authentication, this function's use of AUTH_TYPE_BASIC is appropriate and does not need to change. - - **Modify process ? No** + - process - This function explicitly sets a property named **supportedAuthTypes** to AUTH_TYPE_BASIC. It is unclear why there is no option for in this logic for the use of an ssh-key. + - **Modify process ? Maybe** + + packages\zosuss\src\Shell.ts + + - connect - This function explicitly checks for an ssh key (first) or a password (second) in a hard-coded fashion. If we want the user's authOrder to apply to ssh connections, this function must use the proposed selectPreferredAuth() utility function to to make the right authentication choice. + - **Modify connect ? Yes** ## New functions that must be added @@ -303,9 +310,7 @@ This section describes new functions that must be added to achieve the desired f > --- > - > @internal - > - > public UnknownClass.selectTopAuthType(iSessObj: ISession): void { + > public UnknownClass.selectPreferredAuth(iSessObj: ISession): void { > > - This function should use the new getAuthOrder function to get the ordered array of authentications. > - It should confirm if the authentications (in the preferred order) and their associated properties are available in the iSessObj. From f29132d0de639aca89d04380a3140c3d44c1c0c7 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Tue, 19 Nov 2024 17:03:37 -0500 Subject: [PATCH 06/61] Clean up before draft PR Signed-off-by: Gene Johnston --- docs/Design_for_selecting_auth_type.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/Design_for_selecting_auth_type.md b/docs/Design_for_selecting_auth_type.md index fbf2134e2f..81a265dbd8 100644 --- a/docs/Design_for_selecting_auth_type.md +++ b/docs/Design_for_selecting_auth_type.md @@ -1,6 +1,6 @@ # Order of authentication in Zowe Clients -This document identifies a design to enable users to specify the order in which credentials are selected for authentication when multiple credentials are specified by the user. +This document proposes a design to enable users to specify the order in which credentials are selected for authentication when multiple credentials are specified by the user. Users may not intentionally specify multiple credentials for the same operation. However, because configuration properties can be inherited from a base profile or within nested profiles, it is possible that multiple credentials may be available when a Zowe client attempts to make a connection to a mainframe service. @@ -103,7 +103,7 @@ As an example, the user could specify their desired authOrder like this:     "host": ... ,     "port": ... ,     "rejectUnauthorized": ... , -    "authOrder": [ "basic", "token", "cert-pem"] +    "authOrder": [ "basic", "token", "cert-pem" ] } ``` @@ -218,7 +218,7 @@ The set of candidates for modification consist of all functions that contain the - imperative\src\rest\src\session\Session.ts - - createFromUrl - This function is only called from ImportHandler.buildSession when to enable importing a config from a URL. As with ImportHandler.buildSession, the use of AUTH_TYPE_BASIC when user & password exist is appropriate and should not need to change. + - createFromUrl - This function is only called from ImportHandler.buildSession to enable importing a config from a URL. As with ImportHandler.buildSession, the use of AUTH_TYPE_BASIC when user & password exist is appropriate and should not need to change. - **Modify createFromUrl ? No** - imperative\src\rest\src\session\doc\IOptionsForAddConnProps.ts @@ -246,21 +246,23 @@ The set of candidates for modification consist of all functions that contain the This section describes new functions that must be added to achieve the desired functionality. +This section is a work in progress. The ideas are still pipe dreams and not confirmed by analysis of our code. + - Utility function to record the order of authentication types. > --- > > @internal > - > public UnknownClass.recordAuthOrderFromConfig(tokenIsTopDefault: boolean = false): string[ ] { + > public ClassNotDecidedYet.recordAuthOrderFromConfig(tokenIsTopDefault: boolean = false): string[ ] { > - > - as siblingThis function should obtain the customer-defined authentication order from the Zowe client config file. + > - This function should obtain the customer-defined authentication order from the Zowe client config file. > > - It must confirm that the customer specified valid values. If not, it should record the error, and fall-back to the appropriate default order. > > - It should place those authentications into a string array that is returned. > - > - Maybe instead of returning that array, the array is set into come commonly accessible object (like ImperativeConfig)? + > - Maybe instead of returning that array, the array is set into come commonly accessible object (like the Config class)? > > - If no order has been configured into zowe.config.json, it should create a default order to be backward compatible. > @@ -298,11 +300,11 @@ This section describes new functions that must be added to achieve the desired f > --- > - > public UnknownClass.getAuthOrder(): string[ ] { + > public ClassNotDecidedYet.getAuthOrder(): string[ ] { > > - This function should return the recorded array of authentication types. They will be in the order of top preference first. > - > - Maybe this function lives in ImperativeConfig?. + > - Maybe this function lives in Config?. > > } @@ -310,7 +312,7 @@ This section describes new functions that must be added to achieve the desired f > --- > - > public UnknownClass.selectPreferredAuth(iSessObj: ISession): void { + > public ClassNotDecidedYet.selectPreferredAuth(iSessObj: ISession): void { > > - This function should use the new getAuthOrder function to get the ordered array of authentications. > - It should confirm if the authentications (in the preferred order) and their associated properties are available in the iSessObj. From aef982c5f928f463f8b079b870f8abd3d0c88518 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Mon, 25 Nov 2024 13:57:47 -0500 Subject: [PATCH 07/61] Add section of functions using rejectUnauthorized Signed-off-by: Gene Johnston --- docs/Design_for_selecting_auth_type.md | 76 +++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/docs/Design_for_selecting_auth_type.md b/docs/Design_for_selecting_auth_type.md index 81a265dbd8..e9249f69b8 100644 --- a/docs/Design_for_selecting_auth_type.md +++ b/docs/Design_for_selecting_auth_type.md @@ -141,7 +141,7 @@ That addition would enable customers to also specify the authentication order of - We must notify extenders to guide their customers to supply an appropriate authOrder property if their extension needs a non-default order. -## Determination of functions to be modified +## Functions that reference AUTH_TYPE may need modification The set of candidates for modification consist of all functions that contain the string ***"AUTH_TYPE_"***. This section contains an assessment of whether each such function affects the authentication order and must be modified. @@ -242,6 +242,80 @@ The set of candidates for modification consist of all functions that contain the - connect - This function explicitly checks for an ssh key (first) or a password (second) in a hard-coded fashion. If we want the user's authOrder to apply to ssh connections, this function must use the proposed selectPreferredAuth() utility function to to make the right authentication choice. - **Modify connect ? Yes** +## Functions that reference rejectUnauthorized may need modification + +If we treat **authOrder** like other connection properties, those functions that process **rejectUnauthorized** may also need to process **authOrder**. This section contains an assessment of whether each such function must be modified. + +- packages\cli\src\config\auto-init\ApimlAutoInitHandler.ts + + - doAutoInit - This function uses a connection to APIML. However, it is passed an AbstractSession object. An authOrder property should already be placed into the AbstractSession by a calling function. + - **Modify doAutoInit ? No** + +- packages\cli\src\imperative.ts + + - This class provides definitions used to create the zowe command tree and other CLI operating properties. It includes command-line options for connection properties (like host, port, user, and password). Unless we chose to add authOrder as a command line option (contrary to this proposal) this class should not require modification. + - **Modify imperative.ts? No** + +- packages\core\src\constants\Core.constants.ts + + - BaseProfile - This object contains a schema definition for a base profile. An authOrder property must be added to this object. + - **Modify BaseProfile ? Yes** + +- packages\imperative\src\config\src\ProfileInfo.ts + + - createSession - This function creates a session with key connection properties. An authOrder property must be added to those properties. + - **Modify createSession ? Yes** + +- packages\imperative\src\imperative\src\config\cmd\import\import.handler.ts + + - buildSession - This class imports a config file from a URL. To connect to the URL, this function specifically uses only user & password authentication. It does not access the URL through z/OSMF or APIML. Providing an ability to connect with other credentials for this purpose is beyond the scope of this proposal, and so will not be done as part of this design. + - **Modify buildSession ? No** + +- packages\imperative\src\rest\src\client\AbstractRestClient.ts + + - buildOptions - The constructor for the AbstractRestClient requires an AbstractSession object. That AbstractSession should have already been populated with connection properties. Multiple authentication types should be scrubbed from the AbstractSession by earlier code. Therefore, no change should be required in buildOptions. + - **Modify buildOptions ? No** + +- packages\imperative\src\rest\src\client\ProxySettings.ts + + - getProxyAgent - This function requires an ISession object. The ISession.authTypeOrder should have already been populated. Therefore, no change should be required in getProxyAgent + - **Modify getProxyAgent ? No** + +- packages\imperative\src\rest\src\client\doc\IHTTPSOptions.ts + + - IHTTPSOptions - This interface is only used by AbstractRestClient. Credentials are never extracted from nor added to this an instance of this interface. Therefore there is no reason to add authOrder to this interface. + - **Modify IHTTPSOptions ? No** + +- packages\imperative\src\rest\src\session\AbstractSession.ts + + - buildSession - This function was analyzed in the previous section of this document. + - **Modify buildSession ? Yes** + +- packages\imperative\src\rest\src\session\doc\ISession.ts + + - authTypeOrder - This property was analyzed in the previous section of this document. + - **Modify authTypeOrder ? Maybe** + +- packages\zosjobs\src\GetJobs.ts + + - getJob - This function displays rejectUnauthorized in a diagnostic message. No need to process authOrder here. + - **Modify getJob ? No** + +- packages\zosmf\src\ZosmfSession.ts + + - This Class contains option definitions for connection properties that can be defined in profiles. A definition of the authOrder connection property with a name like ZOSMF_OPTION_AUTH_ORDER should be added. If we choose to not allow authOrder to be specified on the command line (as recommended by this proposal), we may have to provide a definition someplace else. The **autoSave** property could be similar example. + - **Modify ZosmfSession.ts ? Yes** + +- packages\zosmf\src\constants\Zosmf.messages.ts + + - This class provides message text used to display error details. There is no clear reason to add authOrder to this class. + - **Modify Zosmf.messages.ts ? No** + +- packages\zosmf\src\constants\Zosmf.profile.ts + + - ZosmfProfile - This class provides the property definitions for a zosmf profile type. We must add a definition for the authOrder property. + - **Modify Zosmf.profile.ts ? Yes** + ## New functions that must be added This section describes new functions that must be added to achieve the desired functionality. From 803fbd6afd61a287ff9f02448d5ad55ee8e0053c Mon Sep 17 00:00:00 2001 From: zowe-robot Date: Mon, 25 Nov 2024 22:16:15 +0000 Subject: [PATCH 08/61] Bump version to 8.9.0 [ci skip] Signed-off-by: zowe-robot --- lerna.json | 2 +- npm-shrinkwrap.json | 18 +++++++++--------- packages/cli/CHANGELOG.md | 2 +- packages/cli/package.json | 8 ++++---- packages/workflows/package.json | 4 ++-- packages/zosfiles/CHANGELOG.md | 2 +- packages/zosfiles/package.json | 2 +- packages/zosjobs/package.json | 4 ++-- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lerna.json b/lerna.json index 6c8ef4f5c6..daa5c34cf9 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "8.8.4", + "version": "8.9.0", "command": { "publish": { "ignoreChanges": [ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 91c5676cb2..52e37e5113 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -16269,7 +16269,7 @@ }, "packages/cli": { "name": "@zowe/cli", - "version": "8.8.4", + "version": "8.9.0", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { @@ -16277,12 +16277,12 @@ "@zowe/imperative": "8.8.3", "@zowe/provisioning-for-zowe-sdk": "8.8.3", "@zowe/zos-console-for-zowe-sdk": "8.8.3", - "@zowe/zos-files-for-zowe-sdk": "8.8.4", - "@zowe/zos-jobs-for-zowe-sdk": "8.8.4", + "@zowe/zos-files-for-zowe-sdk": "8.9.0", + "@zowe/zos-jobs-for-zowe-sdk": "8.9.0", "@zowe/zos-logs-for-zowe-sdk": "8.8.3", "@zowe/zos-tso-for-zowe-sdk": "8.8.3", "@zowe/zos-uss-for-zowe-sdk": "8.8.3", - "@zowe/zos-workflows-for-zowe-sdk": "8.8.4", + "@zowe/zos-workflows-for-zowe-sdk": "8.9.0", "@zowe/zosmf-for-zowe-sdk": "8.8.3", "find-process": "1.4.7", "lodash": "4.17.21", @@ -16599,10 +16599,10 @@ }, "packages/workflows": { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "8.8.4", + "version": "8.9.0", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.8.4" + "@zowe/zos-files-for-zowe-sdk": "8.9.0" }, "devDependencies": { "@zowe/cli-test-utils": "8.8.3", @@ -16636,7 +16636,7 @@ }, "packages/zosfiles": { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "8.8.4", + "version": "8.9.0", "license": "EPL-2.0", "dependencies": { "lodash": "^4.17.21", @@ -16678,10 +16678,10 @@ }, "packages/zosjobs": { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "8.8.4", + "version": "8.9.0", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.8.4" + "@zowe/zos-files-for-zowe-sdk": "8.9.0" }, "devDependencies": { "@zowe/cli-test-utils": "8.8.3", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 6779cd3d06..3e2a7e9c9d 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,7 +1,7 @@ # Change Log All notable changes to the Zowe CLI package will be documented in this file. -## Recent Changes +## `8.9.0` -Enhancement: Added new command zowe zos-files download all-members-matching, (zowe files dl amm), to download members matching specified pattern(s). The success message for the Download.allMembers API was changed from originally "Data set downloaded successfully" to "Member(s) downloaded successfully." The change also alters the commandResponse when using the --rfj flag. [#2359](https://github.com/zowe/zowe-cli/pull/2359) diff --git a/packages/cli/package.json b/packages/cli/package.json index e53c6044f0..bfa9205e32 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli", - "version": "8.8.4", + "version": "8.9.0", "zoweVersion": "v3.0.0", "description": "Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.", "author": "Zowe", @@ -62,12 +62,12 @@ "@zowe/imperative": "8.8.3", "@zowe/provisioning-for-zowe-sdk": "8.8.3", "@zowe/zos-console-for-zowe-sdk": "8.8.3", - "@zowe/zos-files-for-zowe-sdk": "8.8.4", - "@zowe/zos-jobs-for-zowe-sdk": "8.8.4", + "@zowe/zos-files-for-zowe-sdk": "8.9.0", + "@zowe/zos-jobs-for-zowe-sdk": "8.9.0", "@zowe/zos-logs-for-zowe-sdk": "8.8.3", "@zowe/zos-tso-for-zowe-sdk": "8.8.3", "@zowe/zos-uss-for-zowe-sdk": "8.8.3", - "@zowe/zos-workflows-for-zowe-sdk": "8.8.4", + "@zowe/zos-workflows-for-zowe-sdk": "8.9.0", "@zowe/zosmf-for-zowe-sdk": "8.8.3", "find-process": "1.4.7", "lodash": "4.17.21", diff --git a/packages/workflows/package.json b/packages/workflows/package.json index e9cf5160de..c32bf129ff 100644 --- a/packages/workflows/package.json +++ b/packages/workflows/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "8.8.4", + "version": "8.9.0", "description": "Zowe SDK to interact with the z/OS workflows APIs", "author": "Zowe", "license": "EPL-2.0", @@ -45,7 +45,7 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.8.4" + "@zowe/zos-files-for-zowe-sdk": "8.9.0" }, "devDependencies": { "@zowe/cli-test-utils": "8.8.3", diff --git a/packages/zosfiles/CHANGELOG.md b/packages/zosfiles/CHANGELOG.md index 3dff530c4f..c113aa5557 100644 --- a/packages/zosfiles/CHANGELOG.md +++ b/packages/zosfiles/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Zowe z/OS files SDK package will be documented in this file. -## Recent Changes +## `8.9.0` - Enhancement: Added a `List.membersMatchingPattern` method to download all members that match a specific pattern.[#2359](https://github.com/zowe/zowe-cli/pull/2359) diff --git a/packages/zosfiles/package.json b/packages/zosfiles/package.json index 0180e6c6a7..c5c305e508 100644 --- a/packages/zosfiles/package.json +++ b/packages/zosfiles/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "8.8.4", + "version": "8.9.0", "description": "Zowe SDK to interact with files and data sets on z/OS", "author": "Zowe", "license": "EPL-2.0", diff --git a/packages/zosjobs/package.json b/packages/zosjobs/package.json index cc0421ed2a..97b4a89bf0 100644 --- a/packages/zosjobs/package.json +++ b/packages/zosjobs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "8.8.4", + "version": "8.9.0", "description": "Zowe SDK to interact with jobs on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -46,7 +46,7 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.8.4" + "@zowe/zos-files-for-zowe-sdk": "8.9.0" }, "devDependencies": { "@zowe/cli-test-utils": "8.8.3", From f8f0021934757e1cfa1d0641e3d0028b9a8d1dfe Mon Sep 17 00:00:00 2001 From: jace-roell Date: Tue, 26 Nov 2024 09:23:14 -0500 Subject: [PATCH 09/61] add tagging for bufferToUss Signed-off-by: jace-roell --- .../__system__/methods/upload/Upload.system.test.ts | 7 +++++-- packages/zosfiles/src/methods/upload/Upload.ts | 7 +++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts b/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts index de22e9569e..b0e4c4b76f 100644 --- a/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts +++ b/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts @@ -719,7 +719,7 @@ describe("Upload USS file", () => { }); afterAll(async () => { - await TestEnvironment.cleanUp(testEnvironment); + //await TestEnvironment.cleanUp(testEnvironment); }); describe("Success Scenarios", () => { @@ -755,11 +755,14 @@ describe("Upload USS file", () => { let error; let uploadResponse; let getResponse; + let tagResponse; + const data: Buffer = Buffer.from(testdata); try { uploadResponse = await Upload.bufferToUssFile(REAL_SESSION, ussname, data, { binary: true }); getResponse = await Get.USSFile(REAL_SESSION, ussname, {binary: true}); + tagResponse = await Utilities.isFileTagBinOrAscii(REAL_SESSION, ussname); } catch (err) { error = err; Imperative.console.info("Error: " + inspect(error)); @@ -767,7 +770,7 @@ describe("Upload USS file", () => { expect(error).toBeFalsy(); expect(getResponse).toEqual(Buffer.from(data.toString())); - + expect(tagResponse).toBe(true); }); it("should upload a USS file from local file", async () => { let error; diff --git a/packages/zosfiles/src/methods/upload/Upload.ts b/packages/zosfiles/src/methods/upload/Upload.ts index 528150b961..02c4cc57ae 100644 --- a/packages/zosfiles/src/methods/upload/Upload.ts +++ b/packages/zosfiles/src/methods/upload/Upload.ts @@ -457,6 +457,7 @@ export class Upload { ImperativeExpect.toNotBeEqual(options.record, true, ZosFilesMessages.unsupportedDataType.message); options.binary = options.binary ? options.binary : false; ImperativeExpect.toNotBeNullOrUndefined(ussname, ZosFilesMessages.missingUSSFileName.message); + const origUssname = ussname; ussname = ZosFilesUtils.sanitizeUssPathForRestCall(ussname); const endpoint = ZosFilesConstants.RESOURCE + ZosFilesConstants.RES_USS_FILES + "/" + ussname; @@ -487,6 +488,12 @@ export class Upload { apiResponse.etag = uploadRequest.response.headers.etag; } + if (options.encoding != null) { + await Utilities.chtag(session, origUssname, Tag.TEXT, options.encoding); + } else if (options.binary) { + await Utilities.chtag(session, origUssname, Tag.BINARY); + } + return { success: true, commandResponse: ZosFilesMessages.dataSetUploadedSuccessfully.message, From d44c75f5575c650d810790c044c416bddb53b00f Mon Sep 17 00:00:00 2001 From: jace-roell Date: Tue, 26 Nov 2024 09:32:12 -0500 Subject: [PATCH 10/61] changelog Signed-off-by: jace-roell --- packages/zosfiles/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/zosfiles/CHANGELOG.md b/packages/zosfiles/CHANGELOG.md index c113aa5557..55ffffcc1e 100644 --- a/packages/zosfiles/CHANGELOG.md +++ b/packages/zosfiles/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the Zowe z/OS files SDK package will be documented in this file. +## Recent Changes + +- BugFix: Corrected `Upload.BufferToUssFile` to properly tag uploaded files. [#2378](https://github.com/zowe/zowe-cli/pull/2378) + ## `8.9.0` - Enhancement: Added a `List.membersMatchingPattern` method to download all members that match a specific pattern.[#2359](https://github.com/zowe/zowe-cli/pull/2359) From c0d3c5f60e8a4a9069522ddeb6129b8086a357d3 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Tue, 26 Nov 2024 09:32:41 -0500 Subject: [PATCH 11/61] Fix Signed-off-by: jace-roell --- .../__tests__/__system__/methods/upload/Upload.system.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts b/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts index b0e4c4b76f..158729d6ce 100644 --- a/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts +++ b/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts @@ -719,7 +719,7 @@ describe("Upload USS file", () => { }); afterAll(async () => { - //await TestEnvironment.cleanUp(testEnvironment); + await TestEnvironment.cleanUp(testEnvironment); }); describe("Success Scenarios", () => { From 3d5e7c26780e92dc2c033df3677c09c08d34b7fb Mon Sep 17 00:00:00 2001 From: jace-roell Date: Tue, 26 Nov 2024 10:11:49 -0500 Subject: [PATCH 12/61] chtag mock in unit tests Signed-off-by: jace-roell --- .../__tests__/__unit__/methods/upload/Upload.unit.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts index 7e7e8bf363..603d7181aa 100644 --- a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts +++ b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts @@ -1661,6 +1661,9 @@ describe("z/OS Files - Upload", () => { expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data }); }); it("should return with proper response when upload USS file in binary", async () => { + const chtagSpy = jest.spyOn(Utilities, "chtag"); + chtagSpy.mockImplementation(async (): Promise => null); + const data: Buffer = Buffer.from("testing"); const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); const headers = [ZosmfHeaders.OCTET_STREAM, ZosmfHeaders.X_IBM_BINARY, ZosmfHeaders.ACCEPT_ENCODING]; From 9ee18b97061ec05607e444fa006dfd172850fb79 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Wed, 4 Dec 2024 18:31:41 -0500 Subject: [PATCH 13/61] Add AuthOrder class and update design doc Signed-off-by: Gene Johnston --- docs/Design_for_selecting_auth_type.md | 235 ++++++------- .../src/rest/src/session/AuthOrder.ts | 326 ++++++++++++++++++ 2 files changed, 438 insertions(+), 123 deletions(-) create mode 100644 packages/imperative/src/rest/src/session/AuthOrder.ts diff --git a/docs/Design_for_selecting_auth_type.md b/docs/Design_for_selecting_auth_type.md index e9249f69b8..88c7ed944b 100644 --- a/docs/Design_for_selecting_auth_type.md +++ b/docs/Design_for_selecting_auth_type.md @@ -8,7 +8,7 @@ Users may not intentionally specify multiple credentials for the same operation. A user may use the same user and password to authenticate to most of their services. It makes sense to place that user & password in a base profile so that they are automatically available to every service. This reduces redundancy and reduces maintenance efforts. If one plugin requires a token for authentication, the user would store a token value within that plugin's profile. For that plugin, both the user & password and a token will be available when Zowe CLI attempts to make a connection to that service. For this example, the token is the right choice for this service. For historical reasons, Zowe always selects a user & password over a token when both are available. The use of user & password does not give the desired results. -When a site gradually deploys API-ML, they will very likely encounter another (but opposite) authentication issue. Sites login to APIML to obtain a token, which is then used to authenticate all future requests to services through API-ML. The API-ML token is typically stored in a base profile so that connections to all services are done through API-ML with its token. When a new service is brought on-line at a site, it is common for that service to not be immediately integrated with APIML. For at least a period of time, the site makes a direct connection to that service. The site adds user/password properties to that service's profile to authenticate that direct connection. Once again, both user & password and a token are available when Zowe attempts to connect to the service for that profile. In this case, the user & password are the right choice for this service. This is the opposite choice from the previous example. +In another example, sites gradually deploy API-ML and can easily encounter another (but opposite) authentication issue. Sites login to APIML to obtain a token, which is then used to authenticate all future requests to services through API-ML. The API-ML token is typically stored in a base profile so that connections to all services are done through API-ML with its token. When a new service is brought on-line at a site, it is common for that service to not be immediately integrated with APIML. For at least a period of time, the site makes a direct connection to that service. The site adds user/password properties to that service's profile to authenticate that direct connection. Once again, both user & password and a token are available when Zowe attempts to connect to the service for that profile. In this case, the user & password are the right choice for this service. However, this is the opposite choice from the previous example. As these examples demonstrate, Zowe cannot simply change which authentication type should be given preference. It varies based on what a site is trying to do. That order might also change from one part of the customer's configuration to another. The preferred order in which credentials are chosen is further complicated when we consider that certificates may also be used by a site for some of its services. @@ -20,7 +20,7 @@ In this section we identify the key features that a solution would have to provi - The user must be able to change that authentication order for different parts of the Zowe client configuration. -- Zowe client logic must be enhanced to select the authentication type for a profile used to make a connection based on a user-specified preferred order. +- Zowe client logic must be enhanced to select the authentication type for a profile based on a user-specified preferred order. - Zowe client extenders (CLI plugins and ZE extensions) should **not** be able to alter the order of authentication types. The user should control that choice. @@ -30,19 +30,19 @@ In this section we identify the key features that a solution would have to provi - Zowe has an order of precedence for obtaining property values (config file, environment variable, command line). While a command line option will override the same property stored in a config file, it should not alter the order of authentication. - - For example, if a user specifies a token value on the command line, it will override a token value stored in a config file. However, + - For example, assume that a user has specified that a certificate should be used before a token. Assume that a certificate is supplied in a config file and a token is supplied on the command line. - - If the user has specified that a certificate should be used before a token, and a certificate is also available in the configuration, the certificate should be used because the user configured that certificates should be used before tokens. + - The certificate should be used because the user configured that certificates should be used before tokens. - The token should not be used just because it was supplied on the command line. - The authentication order only identifies the order in which Zowe chooses the **one** authentication method that will be used. If that first authentication method fails, Zowe will not make a second attempt to authenticate with any of the later authentication methods. -- Once an authentication is selected, our logic should ensure that only that one type of authentication is placed into a session object. Thus, logic in down-stream handlers will not alter the order of authentication selection, simply by testing for the authentications within the session in a different order than the order that the user specified. +- Once an authentication is selected, our logic should ensure that only that one type of authentication is placed into a session object. Thus, logic in down-stream Zowe code will not alter the order of authentication selection, simply by testing for the authentications from the session in a different order than the order that the user specified. - - If we were to continue to allow multiple authentications to be placed into a session, we will have to re-work various functions to test for authentications in the desired order. We will also have to provide the object containing that well-defined order to each such function. This will increase the amount of code being changed, and thus increase the probability of mistakes. + - If we were to continue to allow multiple authentications to be placed into a session, we will have to re-work various functions to test for authentications in the desired order. We will also have to provide the object containing that well-defined order to each such function. This will increase the amount of code being changed, and thus increase the time to market and increase the probability of mistakes. -- Zowe clients do not currently support AUTH_TYPE_CERT_PFX, so we cannot add it to a set of available authentications. If AUTH_TYPE_CERT_PFX is implemented, it should be placed immediately after AUTH_TYPE_CERT_PEM in the default order. +- Zowe clients do not currently support AUTH_TYPE_CERT_PFX, so we cannot add it to a set of available authentications at this time. If AUTH_TYPE_CERT_PFX is implemented, it should be placed immediately after AUTH_TYPE_CERT_PEM in the default order. - Customers should be able to specify AUTH_TYPE_NONE in their preferred order of authentications. While it is not advisable to have no authentication, if a customer has a service that requires no authentication, the customer should be able to specify AUTH_TYPE_NONE at the top of their list of authentications applicable to that particular profile. @@ -50,6 +50,8 @@ In this section we identify the key features that a solution would have to provi - A customer-specified list of authentications must contain at least one of our supported authentications. +- The `--show-input-only` option should show the order of authentication as part of its displayed connection properties. + ## Historical behavior The objective of this feature is to enable users to define the order in which an authentication type is selected. However, when a user does not specify any such order, the default order should reflect past behavior. @@ -57,21 +59,15 @@ The objective of this feature is to enable users to define the order in which an - The AbstractRestClient currently enforces an order of: - AUTH_TYPE_TOKEN - - AUTH_TYPE_BASIC - - AUTH_TYPE_BEARER - - AUTH_TYPE_CERT_PEM - Zowe classes other than AbstractRestClient (like AbstractSession) currently override the authentication order from AbstractRestClient into: - AUTH_TYPE_BASIC - - - AUTH_TYPE_BEARER - - AUTH_TYPE_TOKEN - + - AUTH_TYPE_BEARER - AUTH_TYPE_CERT_PEM These selections of authentication should be maintained as the default selections for their respective classes to avoid introducing a breaking change. @@ -86,17 +82,25 @@ A new profile property named **authOrder** should be created to enable users to - A parent profile of a nested configuration. - - Any profile of type **zosmf**. + - Any service profile. - Any profile specific to a plugin (or VSCode extension) that supports a REST connection. For example an **endevor** profile could contain an **authOrder** property, but an **endevor-location** profile would not. - Our existing inheritance of connection properties should also apply to the inheritance of the authOrder property. - We should be able to use our logic for where and how the **rejectUnauthorized** property is handled as a model for how we handle the **authOrder** property. + +- A new property can be added to the **properties** of any profile. Since we are proposing that **authOrder** be handled by imperative functions, no CLI plugin or ZE extension will need modification for the **authOrder** property to be correctly handled. + +- Such a new item within the properties object will not currently be included in the zowe.schema.json file. An IntelliSense-like editor will not display **authOrder** as an option when a user starts to add a new property in a profile. + + - We do not want to require plugins/extensions to add **authOrder** to their profiles. Requesting new work from plugins/extensions in the middle of a release's lifecycle can be a burden for those contributors. - - One difference from **rejectUnauthorized** is that for **authOrder** we should accept its value from a zowe.config.json file, but not from a command line argument or environment variable. Because **authOrder** is an array, it will be difficult and error-prone for users to correctly specify **authOrder** on a command line or in an environment variable. + - When the CLI is installed, the schema is not updated, so the CLI cannot currently take on that burden. It is possible that a CLI post-install step could be performed to update the schema. This is not considered to be a trivial task. + + - It should be noted if **authOrder** is absent from the schema, users will lose a nice convenience, but the user's config will not be broken in any functional way. -As an example, the user could specify their desired authOrder like this: +To represent a series of values, the **authOrder** property should be an array. The following example shows how a user could specify their desired authOrder. ``` "properties": { @@ -110,7 +114,7 @@ As an example, the user could specify their desired authOrder like this: The programmatic definition of authOrder would be: ``` -authOrder[SessConstants.AUTH_TYPE_CHOICES]    +authOrder: SessConstants.AUTH_TYPE_CHOICES[] ``` The current set of AUTH_TYPE_CHOICES are: @@ -141,18 +145,82 @@ That addition would enable customers to also specify the authentication order of - We must notify extenders to guide their customers to supply an appropriate authOrder property if their extension needs a non-default order. +## A new class must be created to support authOrder + +A new class located in + +    [zowe-cli/packages/imperative/src/rest/src/session/AuthOrder.ts](https://github.com/zowe/zowe-cli/blob/master/packages/imperative/src/rest/src/session/AuthOrder.ts) + +should be implemented to detect the authentication order supplied by a user, and place the correct set of credentials into a session. The class currently exists as a workable proof of concept. With no confirmation of the many edge cases, it does appear to accomplished the basic needs. It can be finalized once it is fully integrated with existing Zowe logic. + +This class is declared **@internal** which will limit its use to the imperative package. More access can be provided during implementation if we identify additional places in Zowe code that need to use functions from this class. + +Functions in the AuthOrder class include: + +- setTopDefaultAuth - This function will set the top authentication choice (either basic or token) when a default authOrder must be created because the user did not supply an auth order. Through the use of this function we can maintain backward compatibility and not introduce a breaking change. + + When authOrder has not been configured into zowe.config.json, we create a default order to be backward compatible. + + - If an argument of AUTH_TYPE_TOKEN is supplied, it should place token at the top of the order, resulting in this order: + + - AUTH_TYPE_TOKEN + + - AUTH_TYPE_BASIC + + - AUTH_TYPE_BEARER + + - AUTH_TYPE_CERT_PEM + + - AUTH_TYPE_NONE + + - If AUTH_TYPE_BASIC is supplied (or this function is not called), it should place basic at the top of the order, resulting in this order: + + - AUTH_TYPE_BASIC + + - AUTH_TYPE_TOKEN + + -  AUTH_TYPE_BEARER + + - AUTH_TYPE_CERT_PEM + + - AUTH_TYPE_NONE + + - It should be called from AbstractRestClient.constructor to replace its hard-coded array of credential types. + + - It might be called from other existing locations as needed. + +- putTopAuthInSession - This function will find the highest auth type (according to the authOrder) which exists in either the supplied session config or command line arguments, place the credentials associated with that auth type into the supplied session config, and remove the credentials for all other auth types from the supplied session config. + + - It might be called from ConnectionPropsForSessCfg.addPropsOrPrompt. + + - By temporarily modifying a local copy of addPropsOrPrompt to call putTopAuthInSession, I confirmed that the resulting session object contained only those credentials obtained from the command arguments associated with highest authentication type (as determined from the authOrder). + + - It might be called from ConnectionPropsForSessCfg.resolveSessCfgProps. + + - It might be called from ProfileInfo.createSession. + + - While apps like ZE do not take command line arguments, they do form an ICommandArguments object. The createSesion function already has such an object, so it can be passed to putTopAuthInSession. + + - Any other location in ZE-related code which needs to call putTopAuthInSession will need to form an ICommandArguments object. + + - It might be called from other existing locations as needed. + +- cacheAuthOrder - This function stores the authOrder property from the supplied command arguments for later use. In the prototype, it is only called from putTopAuthInSession. However, cacheAuthOrder is available should we find that we need to to call it from other locations (like at the end of the CommandProcessor.prepare function). + +- removeExtraCredsFromSess - This function removes all credential properties from the supplied session except for the top available authentication type. In the prototype, it is only called from putTopAuthInSession. However, removeExtraCredsFromSess is available should we find that we must scrub unneeded credentials from a session in other location in existing Zowe code. + ## Functions that reference AUTH_TYPE may need modification The set of candidates for modification consist of all functions that contain the string ***"AUTH_TYPE_"***. This section contains an assessment of whether each such function affects the authentication order and must be modified. - cli\src\config\auto-init\ApimlAutoInitHandler - - doAutoInit - This function logins into APIML with the session object if either user & password or cert are in the session object. doAutoInit does not make a selection of order. It lets Login.apimlLogin() make that decision. If only the selected authentication is placed into a session, then no need to change. + - doAutoInit - This function logins into APIML with the session object if either user & password or cert are in the session object. doAutoInit does not make a selection of order. However, it is passed an AbstractSession object. The session credentials should already have been placed into the AbstractSession by a previously called function - **Modify doAutoInit ? No** - core\src\rest\ZosmfRestClient.ts - - processError - This function just alters error message text based on authentications found in the session. If only the selected authentication is placed into a session, then no need to change. + - processError - This function just alters error message text based on authentications found in the session. If only the top authentication type resides in a session, then no need to change. - **Modify processError ? No** - imperative\src\config\src\ConfigAutoStore.ts @@ -173,11 +241,11 @@ The set of candidates for modification consist of all functions that contain the - **Modify buildOptions ? No** - - constructor - This function currently hard-codes an order of authentication types into the ISession.authTypeOrder array. We must create a means to record the customer-defined order in this function. This function should call a common function (tentatively named recordAuthOrderFromConfig) to do this work. recordAuthOrderFromConfig should be able to set the old hard-coded order (as the default order) only if a customer does not specify an order. + - constructor - This function currently hard-codes an order of authentication types into the ISession.authTypeOrder array contained the supplied session. After AuthOrder is implemented, the ISession.authTypeOrder array should already be set in the session which is passed as an argument to this constructor. We should remove the logic that hard-codes the authTypeOrder into the session. - **Modify constructor? yes** - - Each of the following functions reference AUTH_TYPE_XXX to a place an identified type into the ISession.type property. Since buildOptions calls just one of the following functions based on being the first available authentication in the ISession.authTypeOrder array, none of these functions need to change. + - Each of the following functions reference AUTH_TYPE_XXX to a place an identified type into the ISession.type property of the session. Since buildOptions calls just one of the following functions based on being the first available authentication in the ISession.authTypeOrder array, none of these functions need to change. Note that these functions may no longer be necessary since AuthOrder.putTopAuthInSession should have already set the ISession.type property. - **Modify setBearerAuth ? No** @@ -189,23 +257,23 @@ The set of candidates for modification consist of all functions that contain the - imperative\src\rest\src\session\AbstractSession.ts - - buildSession - This private function is called by the constructor, which accepts an Isession object. A caller could populate multiple authentications (and related properties) into that supplied session. Session.buildSession() will have to scrub all but the highest priority available authentication from the session. We should create a common utility function (tentatively named selectPreferredAuth) to do the scrubbing. selectPreferredAuth can be also be called from ConnectionPropsForSessCfg.resolveSessCfgProps function as described below. + - buildSession - This private function is called by the constructor, which accepts an Isession object. A caller could populate multiple authentications (and related properties) into that supplied session. Ideally the caller of the Session.constructor will have already called ConnectionPropsForSessCfg.addPropsOrPrompt() which will have already removed all but the highest priority available authentication from the session. We should confirm that this always true. If not, buildSession may have to call AuthOrder.putTopAuthInSession. We should also check whether assignments to session properties by buildSession will override any of the properties set by AuthOrder.putTopAuthInSession. - - **Modify buildSession ? Yes** + - **Modify buildSession ? Maybe** - - DEFAULT_TYPE - This simply a constant definition set to AUTH_TYPE_NONE. It is not used in any CLI or ZE code outside of this AbstractSession class. Because it is a public property, it cannot be removed without risk of breaking change. If AUTH_TYPE_NONE is added to the ISession.authTypeOrder array, DEFAULT_TYPE should be deprecated. + - DEFAULT_TYPE - This is simply a constant definition set to AUTH_TYPE_NONE. It is not used in any CLI or ZE code outside of this AbstractSession class. Because it is a public property, it cannot be removed without risk of breaking change. If AUTH_TYPE_NONE is added to the ISession.authTypeOrder array, DEFAULT_TYPE should be deprecated. - **Modify DEFAULT_TYPE ? Yes** - imperative\src\rest\src\session\ConnectionPropsForSessCfg.ts - - addPropsOrPrompt - This function only uses AUTH_TYPE_XXX to determine whether a token and a cert are irrelevant based on the existence of AUTH_TYPE_TOKEN. Those items should not need to change. However, addPropsOrPrompt accepts three parameters, each of which can have property overrides of authentication. After calling resolveSessCfgProps, addPropsOrPrompt continues to modify the session properties with values from its parameters. Thus addPropsOrPrompt must be refactored to work properly with a refactored resolveSessCfgProps. + - addPropsOrPrompt - Near the end of this function, a call to AuthOrder.putTopAuthInSession will ensure that the right authentication resides in the session. - **Modify addPropsOrPrompt ? Yes** - - resolveSessCfgProps - Many functions call this function before creating a new session. This function could scrub all but the selected authentication and related properties from the session object. However, callers could call 'new Session()' without first calling resolveSessCfgProps(). Thus, Session.buildSession() will have to perform the same scrubbing of authentications from the session. Both Session.buildSession and resolveSessCfgProps should call selectPreferredAuth() to do the scrubbing. + - resolveSessCfgProps - Several functions call this function before creating a new session. Either this function must call AuthOrder.putTopAuthInSession, or each caller of resolveSessCfgProps must first call putTopAuthInSession. - - **Modify resolveSessCfgProps ? Yes** + - **Modify resolveSessCfgProps ? Maybe** - setTypeForTokenRequest - This function handles setting authentication to AUTH_TYPE_TOKEN to get a token back from user & password. This does not appear to require any change, but it should be revisited after resolveSessCfgProps is refactored. @@ -228,18 +296,18 @@ The set of candidates for modification consist of all functions that contain the - imperative\src\rest\src\session\doc\ISession.ts - - authTypeOrder - This property could be the focus of our refactoring, but currently it is hard-coded and only used in AbstractRestClient.constructor & AbstractRestClient.buildOptions. This property should be used to hold the customer-defined order of authentication types. There is no reason to change this property. Other code will repopulate authTypeOrder's set of values based on customer input. It is possible that an ISession may not be available at the time we want to store the customer-defined order of authentication types. Another object may need to store that order, which is later transferred into this ISession property. The only reason that we may want to change this item is to rename it from authtypeOrder to authOrder to reflect the same, simpler object name that a user will use to specify the authentication order. We should only change the name of authTypeOrder if it is only used internally by Zowe (and thus would be a non-breaking change). + - authTypeOrder - This property is used to hold the order of authentication types. It is currently populated by hard-coded login and is only used in AbstractRestClient.constructor & AbstractRestClient.buildOptions. There is no reason to change this property. AuthOrder.putTopAuthInSession should populate authTypeOrder's set of values based on customer input. The only change for authTypeOrder will be to remove the comment that states that this property is hard-coded. - - **Modify authTypeOrder ? Maybe** + - **Modify authTypeOrder ? Yes** - packages\zosuss\src\SshBaseHandler.ts - - process - This function explicitly sets a property named **supportedAuthTypes** to AUTH_TYPE_BASIC. It is unclear why there is no option for in this logic for the use of an ssh-key. + - process - This function explicitly sets a property named **supportedAuthTypes** to AUTH_TYPE_BASIC. It is unclear why there is no option in this logic to use an ssh-key. - **Modify process ? Maybe** packages\zosuss\src\Shell.ts - - connect - This function explicitly checks for an ssh key (first) or a password (second) in a hard-coded fashion. If we want the user's authOrder to apply to ssh connections, this function must use the proposed selectPreferredAuth() utility function to to make the right authentication choice. + - connect - This function explicitly checks for an ssh key (first) or a password (second) in a hard-coded fashion. If we want the user's authOrder to apply to ssh connections, this function must call the proposed AuthOrder.putTopAuthInSession to to make the right authentication choice. - **Modify connect ? Yes** ## Functions that reference rejectUnauthorized may need modification @@ -248,13 +316,13 @@ If we treat **authOrder** like other connection properties, those functions that - packages\cli\src\config\auto-init\ApimlAutoInitHandler.ts - - doAutoInit - This function uses a connection to APIML. However, it is passed an AbstractSession object. An authOrder property should already be placed into the AbstractSession by a calling function. - - **Modify doAutoInit ? No** + - doAutoInit - This function was analyzed in the previous section of this document. + - **Modify doAutoInit ? No** - packages\cli\src\imperative.ts - - This class provides definitions used to create the zowe command tree and other CLI operating properties. It includes command-line options for connection properties (like host, port, user, and password). Unless we chose to add authOrder as a command line option (contrary to this proposal) this class should not require modification. - - **Modify imperative.ts? No** + - This class provides definitions used to create the Zowe command tree and other CLI operating properties. It includes command-line options for connection properties (like host, port, user, and password). We must add **authOrder** as a new command line option into this class. + - **Modify imperative.ts? Yes** - packages\core\src\constants\Core.constants.ts @@ -263,17 +331,17 @@ If we treat **authOrder** like other connection properties, those functions that - packages\imperative\src\config\src\ProfileInfo.ts - - createSession - This function creates a session with key connection properties. An authOrder property must be added to those properties. + - createSession - This function creates a session with key connection properties. Depending on the modification choices made for ConnectionPropsForSessCfg.resolveSessCfgProps, this function may have to call AuthOrder.putTopAuthInSession directly. - **Modify createSession ? Yes** - packages\imperative\src\imperative\src\config\cmd\import\import.handler.ts - - buildSession - This class imports a config file from a URL. To connect to the URL, this function specifically uses only user & password authentication. It does not access the URL through z/OSMF or APIML. Providing an ability to connect with other credentials for this purpose is beyond the scope of this proposal, and so will not be done as part of this design. + - buildSession - This function was analyzed in the previous section of this document. - **Modify buildSession ? No** - packages\imperative\src\rest\src\client\AbstractRestClient.ts - - buildOptions - The constructor for the AbstractRestClient requires an AbstractSession object. That AbstractSession should have already been populated with connection properties. Multiple authentication types should be scrubbed from the AbstractSession by earlier code. Therefore, no change should be required in buildOptions. + - buildOptions - This function was analyzed in the previous section of this document. - **Modify buildOptions ? No** - packages\imperative\src\rest\src\client\ProxySettings.ts @@ -289,21 +357,21 @@ If we treat **authOrder** like other connection properties, those functions that - packages\imperative\src\rest\src\session\AbstractSession.ts - buildSession - This function was analyzed in the previous section of this document. - - **Modify buildSession ? Yes** + - **Modify buildSession ? Maybe** - packages\imperative\src\rest\src\session\doc\ISession.ts - authTypeOrder - This property was analyzed in the previous section of this document. - - **Modify authTypeOrder ? Maybe** + - **Modify authTypeOrder ? No** - packages\zosjobs\src\GetJobs.ts - - getJob - This function displays rejectUnauthorized in a diagnostic message. No need to process authOrder here. + - getJob - This function displays rejectUnauthorized in a diagnostic message. No need to process authOrder here. - **Modify getJob ? No** - packages\zosmf\src\ZosmfSession.ts - - This Class contains option definitions for connection properties that can be defined in profiles. A definition of the authOrder connection property with a name like ZOSMF_OPTION_AUTH_ORDER should be added. If we choose to not allow authOrder to be specified on the command line (as recommended by this proposal), we may have to provide a definition someplace else. The **autoSave** property could be similar example. + - This Class contains option definitions for connection properties that can be defined in profiles. A definition of the authOrder connection property with a name like ZOSMF_OPTION_AUTH_ORDER should be added. - **Modify ZosmfSession.ts ? Yes** - packages\zosmf\src\constants\Zosmf.messages.ts @@ -316,83 +384,4 @@ If we treat **authOrder** like other connection properties, those functions that - ZosmfProfile - This class provides the property definitions for a zosmf profile type. We must add a definition for the authOrder property. - **Modify Zosmf.profile.ts ? Yes** -## New functions that must be added - -This section describes new functions that must be added to achieve the desired functionality. - -This section is a work in progress. The ideas are still pipe dreams and not confirmed by analysis of our code. - -- Utility function to record the order of authentication types. - - > --- - > - > @internal - > - > public ClassNotDecidedYet.recordAuthOrderFromConfig(tokenIsTopDefault: boolean = false): string[ ] { - > - > - This function should obtain the customer-defined authentication order from the Zowe client config file. - > - > - It must confirm that the customer specified valid values. If not, it should record the error, and fall-back to the appropriate default order. - > - > - It should place those authentications into a string array that is returned. - > - > - Maybe instead of returning that array, the array is set into come commonly accessible object (like the Config class)? - > - > - If no order has been configured into zowe.config.json, it should create a default order to be backward compatible. - > - > - If tokenIsTopDefault is true, it should place token at the top of the order, resulting in this order: - > - > - AUTH_TYPE_TOKEN - > - > - AUTH_TYPE_BASIC - > - > - AUTH_TYPE_BEARER - > - > - AUTH_TYPE_CERT_PEM - > - > - AUTH_TYPE_CERT_PFX - > - > - AUTH_TYPE_NONE - > - > - If tokenIsTopDefault is false, it should place basic at the top of the order, resulting in this order: - > - > - AUTH_TYPE_BASIC - > - > - AUTH_TYPE_TOKEN - > - > -  AUTH_TYPE_BEARER - > - > - AUTH_TYPE_CERT_PEM - > - > - AUTH_TYPE_CERT_PFX - > - > - AUTH_TYPE_NONE - > - > } - -- Utility function to get the array of authentication types. - - > --- - > - > public ClassNotDecidedYet.getAuthOrder(): string[ ] { - > - > - This function should return the recorded array of authentication types. They will be in the order of top preference first. - > - > - Maybe this function lives in Config?. - > - > } - -- Utility function to select the top available authentication type in a session. - - > --- - > - > public ClassNotDecidedYet.selectPreferredAuth(iSessObj: ISession): void { - > - > - This function should use the new getAuthOrder function to get the ordered array of authentications. - > - It should confirm if the authentications (in the preferred order) and their associated properties are available in the iSessObj. - > - Once the first authentication is found, the properties related to all other authentications should be removed from iSessObj. - > - Maybe this function lives in AbstractSession?. - > - > } - -# \ No newline at end of file +## \ No newline at end of file diff --git a/packages/imperative/src/rest/src/session/AuthOrder.ts b/packages/imperative/src/rest/src/session/AuthOrder.ts new file mode 100644 index 0000000000..3052c86e72 --- /dev/null +++ b/packages/imperative/src/rest/src/session/AuthOrder.ts @@ -0,0 +1,326 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ICommandArguments } from "../../../cmd"; +import { ImperativeError } from "../../../error"; +import { ISession } from "./doc/ISession"; +import { Logger } from "../../../logger"; +import * as SessConstants from "./SessConstants"; + +/** + * @internal - Cannot be used outside of the imperative package + * + * The purpose of this class is to detect an authentication order property + * supplied by a user in a profile, command line, or environment variable. + * That authOrder is then used to place the correct set of credentials into + * a session for authentication. + */ +export class AuthOrder { + + /** + * When a user does not supply an auth order, Zowe clients will use a + * hard-coded default order. This property records whether AUTH_TYPE_BASIC + * or AUTH_TYPE_TOKEN is the top auth choice in the order. + */ + private static m_topDefaultAuth: string = SessConstants.AUTH_TYPE_BASIC; + + /** + * This array of authentication types specifies the order of preferred + * authentication. It contains the user-specified order, or a default order + * if the user does not specify an order. m_authOrder[0] is the highest + * preferred authentication. + */ + private static m_authOrder: SessConstants.AUTH_TYPE_CHOICES[] = null; + + // *********************************************************************** + /** + * Set the top auth type when a default authOrder is used. Previously, + * two different hard-coded orders were present in the Zowe clients. + * Both hard-coded orders are now provided by this class. Zowe code, + * that still sets a specific order for backward compatibility, now + * calls this function to ensure that that the original behavior remains + * the same and avoids a breaking change when a user has not specified + * an authOrder property. + * + * @param topDefaultAuth - Input. + * The top authentication type that will be used when forming a + * default authOrder. + */ + public static setTopDefaultAuth( + topDefaultAuth: typeof SessConstants.AUTH_TYPE_BASIC | typeof SessConstants.AUTH_TYPE_TOKEN + ): void { + AuthOrder.m_topDefaultAuth = topDefaultAuth; + } + + // *********************************************************************** + /** + * Cache the authOrder property from the supplied cmdArgs. If no authOrder exists + * in cmdArgs, a default authOrder is created and cached. + * + * @param cmdArgs - Input. + * The set of arguments that the calling function is using. + */ + private static cacheAuthOrder(cmdArgs: ICommandArguments): void { + // have we already cached the authOrder? + if (AuthOrder.m_authOrder !== null) { + // start over with an empty order. + AuthOrder.m_authOrder = null; + } + + if (cmdArgs.authOrder) { + // validate each user-supplied type of authentication + for (const nextUserAuth of cmdArgs.authOrder) { + switch (nextUserAuth) { + case SessConstants.AUTH_TYPE_BASIC: + case SessConstants.AUTH_TYPE_TOKEN: + case SessConstants.AUTH_TYPE_BEARER: + case SessConstants.AUTH_TYPE_CERT_PEM: + case SessConstants.AUTH_TYPE_NONE: + if (AuthOrder.m_authOrder === null) { + AuthOrder.m_authOrder = []; + } + AuthOrder.m_authOrder.push(nextUserAuth); + break; + default: + Logger.getImperativeLogger().error( + `The authentication = '${nextUserAuth}' is not valid and will be ignored.` + ); + /* todo: Remove diagnostic print statements + console.log("____ cacheAuthOrder: nextUserAuth = '" + nextUserAuth + "' is not valid and will be ignored."); + // end Remove todo: */ + } + } + } + + // the user supplied an authOrder + if (AuthOrder.m_authOrder !== null) { + /* todo: Remove diagnostic print statements + console.log("____ cacheAuthOrder: cached authOrder = " + AuthOrder.m_authOrder); + // end Remove todo: */ + return; + } + + // No authOrder was supplied by the user. Create a default order. + AuthOrder.m_authOrder = []; + if (AuthOrder.m_topDefaultAuth === SessConstants.AUTH_TYPE_BASIC) { + // we want user & password auth as the top choice + AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_BASIC); + AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_TOKEN); + } else { + // we want token auth as the top choice + AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_TOKEN); + AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_BASIC); + } + // add remaining auth types. We do not include 'none' in our defaults. + AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_BEARER); + AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_CERT_PEM); + /* todo: Remove diagnostic print statements + console.log("____ cacheAuthOrder: cached authOrder = " + AuthOrder.m_authOrder); + // end Remove todo: */ + } + + // *********************************************************************** + /** + * Find the highest auth type (according to the authOrder) which exists + * in either the supplied session config or command line arguments. + * Then place the credentials associated with that auth type into the + * supplied session config. Credentials for all other auth types are + * removed from the session config. + * + * @param sessCfg - Modified. + * Authentication properties are added to and removed from this + * session configuration, which can already have properties in + * this object when passed to this function. + * + * @param cmdArgs - Input. + * The set of arguments with which the calling function is operating. + * For CLI, the cmdArgs come from the command line, profile, or + * environment. Other apps can place relevant arguments into this + * object to be processed by this function. + */ + public static putTopAuthInSession( + sessCfg: SessCfgType, + cmdArgs: ICommandArguments + ): void { + let sessTypeToUse: SessConstants.AUTH_TYPE_CHOICES = null; + + // cache the correct authOrder to use + AuthOrder.cacheAuthOrder(cmdArgs); + + /* todo: Remove diagnostic print statements + sessCfg.tokenType = "apimlAuthenticationToken"; + sessCfg.tokenValue = "SomeTokenValue"; + sessCfg.cert = "./certFile.txt"; + sessCfg.certKey = "./certKeyFile.txt"; + sessCfg.authTypeOrder = []; + sessCfg.authTypeOrder.push("bogusAuthType1"); + sessCfg.authTypeOrder.push("bogusAuthType2"); + sessCfg.authTypeOrder.push("bogusAuthType3"); + sessCfg.authTypeOrder.push("bogusAuthType4"); + console.log("____ putTopAuthInSession:\ncmdArgs = " + JSON.stringify(cmdArgs, null, 2)); + console.log("____ putTopAuthInSession:\nsessCfg before processing = " + JSON.stringify(sessCfg, null, 2)); + // end Remove todo: */ + + // Detect the first auth type (from our auth order) provided in the session config or in command args. + // Ensure that the auth properties are placed in the session config. + // Record the detected auth type for use as the session type. + let errMsg: string; + for (const nextAuth of AuthOrder.m_authOrder) { + switch (nextAuth) { + case SessConstants.AUTH_TYPE_BASIC: + // todo: do we have to check for sessCfg.base64EncodedAuth ? + if (cmdArgs.user?.length > 0) { + sessCfg.user = cmdArgs.user; + } + if (cmdArgs.password?.length > 0) { + sessCfg.password = cmdArgs.password; + } + if (sessCfg.user?.length > 0 && sessCfg.password?.length > 0) { + // TODO: Confirm in ConnectionPropsForSessCfg that requestToken will work ok with sessTypeToUse + sessTypeToUse = SessConstants.AUTH_TYPE_BASIC; + } + break; + case SessConstants.AUTH_TYPE_TOKEN: + if (cmdArgs.tokenType?.length > 0) { + sessCfg.tokenType = cmdArgs.tokenType; + } + if (cmdArgs.tokenValue?.length > 0) { + sessCfg.tokenValue = cmdArgs.tokenValue; + } + if (sessCfg.tokenType?.length > 0 && sessCfg.tokenValue?.length > 0) { + sessTypeToUse = SessConstants.AUTH_TYPE_TOKEN; + } + break; + case SessConstants.AUTH_TYPE_BEARER: + if (cmdArgs.tokenType?.length > 0) { + sessCfg.tokenType = cmdArgs.tokenType; + } + if (cmdArgs.tokenValue?.length > 0) { + sessCfg.tokenValue = cmdArgs.tokenValue; + } + // a tokenValue with no tokenType implies a bearer token + if (!(sessCfg.tokenType?.length > 0) && sessCfg.tokenValue?.length > 0) { + sessTypeToUse = SessConstants.AUTH_TYPE_BEARER; + } + break; + case SessConstants.AUTH_TYPE_CERT_PEM: + if (cmdArgs.certFile?.length > 0) { + sessCfg.cert = cmdArgs.certFile; + } + if (cmdArgs.certKeyFile?.length > 0) { + sessCfg.certKey = cmdArgs.certKeyFile; + } + if (sessCfg.cert?.length > 0 && sessCfg.certKey?.length > 0) { + sessTypeToUse = SessConstants.AUTH_TYPE_CERT_PEM; + } + break; + case SessConstants.AUTH_TYPE_NONE: + sessTypeToUse = SessConstants.AUTH_TYPE_NONE; + break; + default: + // authOrder was validated. A wrong value now is our programming error. + errMsg = `authOrder contains an invalid authentication = ${nextAuth}.`; + Logger.getImperativeLogger().error(errMsg); + throw new ImperativeError({ msg: errMsg }); + } + if (sessTypeToUse !== null) { + // stop looking for auth types after we find the first one + break; + } + } + + // When no creds are in the session and AUTH_TYPE_NONE is not in the user's authOrder, + // remove the session type from the session. Otherwise set the type that we found. + if (sessTypeToUse === null) { + delete sessCfg.type; + } else { + sessCfg.type = sessTypeToUse; + } + + // remove all extra auth creds from the session + AuthOrder.removeExtraCredsFromSess(sessCfg); + + // copy our authOrder into the session object + sessCfg.authTypeOrder = [...AuthOrder.m_authOrder]; + + // todo: Should we throw error if no creds are in the session, or let other functions throw the error? + + /* todo: Remove diagnostic print statements + console.log("____ putTopAuthInSession:\nsessCfg after processing = " + JSON.stringify(sessCfg, null, 2)); + // end Remove todo: */ + } + + // *********************************************************************** + /** + * Remove all credential properties from the supplied session except for the + * creds related to the session type specified within the sessCfg argument. + * + * @param sessCfg - Modified. + * Authentication credentials are removed from this session configuration. + */ + private static removeExtraCredsFromSess( + sessCfg: SessCfgType + ): void { + if (AuthOrder.cacheAuthOrder == null) { + const errMsg = "AuthOrder.cacheAuthOrder must be called before AuthOrder.removeExtraCredsFromSess"; + Logger.getImperativeLogger().error(errMsg); + throw new ImperativeError({ msg: errMsg }); + } + if (!sessCfg?.type) { + const errMsg = "Session type must exist in the supplied session."; + Logger.getImperativeLogger().error(errMsg); + throw new ImperativeError({ msg: errMsg }); + } + + // initially set all creds to be removed from the session. Later we delete the desired creds from this set + const credsToRemove = new Set(["user", "password", "base64EncodedAuth", "tokenType", "tokenValue", "cert", "certKey"]); + + // Delete the selected creds from the set of creds that will be removed from our session config. + let errMsg: string; + switch (sessCfg.type) { + case SessConstants.AUTH_TYPE_BASIC: + credsToRemove.delete("user"); + credsToRemove.delete("password"); + credsToRemove.delete("base64EncodedAuth"); + break; + case SessConstants.AUTH_TYPE_TOKEN: + credsToRemove.delete("tokenType"); + credsToRemove.delete("tokenValue"); + break; + case SessConstants.AUTH_TYPE_BEARER: + credsToRemove.delete("tokenValue"); + break; + case SessConstants.AUTH_TYPE_CERT_PEM: + credsToRemove.delete("cert"); + credsToRemove.delete("certKey"); + break; + case SessConstants.AUTH_TYPE_NONE: + break; + default: + // authOrder was validated. A wrong value now is our programming error. + errMsg = `Session an invalid type = ${sessCfg.type}.`; + Logger.getImperativeLogger().error(errMsg); + throw new ImperativeError({ msg: errMsg }); + } + + // remove all auth creds from the session, except the creds for the auth type that we chose to keep + const credIter = credsToRemove.values(); + let nextCredToRemove = credIter.next(); + while (!nextCredToRemove.done) { + /* todo: Remove diagnostic print statements + console.log("____ removeExtraCredsFromSess: deleting = 'sessCfg." + nextCredToRemove.value + "' from the session."); + // end Remove todo: */ + + delete (sessCfg as any)[nextCredToRemove.value]; + nextCredToRemove = credIter.next(); + } + } +} \ No newline at end of file From 6f098f38f81c7fe2e2d9f0d984919358076d52f0 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Fri, 6 Dec 2024 14:24:54 -0500 Subject: [PATCH 14/61] changelog and test expect Signed-off-by: jace-roell --- packages/zosfiles/CHANGELOG.md | 2 +- .../__tests__/__unit__/methods/upload/Upload.unit.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/zosfiles/CHANGELOG.md b/packages/zosfiles/CHANGELOG.md index 55ffffcc1e..4667f7ffce 100644 --- a/packages/zosfiles/CHANGELOG.md +++ b/packages/zosfiles/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to the Zowe z/OS files SDK package will be documented in thi ## Recent Changes -- BugFix: Corrected `Upload.BufferToUssFile` to properly tag uploaded files. [#2378](https://github.com/zowe/zowe-cli/pull/2378) +- BugFix: Corrected `Upload.BufferToUssFile()` SDK function to properly tag uploaded files. [#2378](https://github.com/zowe/zowe-cli/pull/2378) ## `8.9.0` diff --git a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts index 603d7181aa..28812678c8 100644 --- a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts +++ b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts @@ -1676,7 +1676,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeUndefined(); expect(USSresponse).toBeDefined(); - + expect(chtagSpy).toHaveBeenCalled(); expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data }); }); From 49ff82f473ed06ed3701a4b9c167b3fcdc16e961 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Mon, 9 Dec 2024 09:50:40 -0500 Subject: [PATCH 15/61] remove comment, add apiResponse Signed-off-by: jace-roell --- packages/zosfiles/src/methods/upload/Upload.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/zosfiles/src/methods/upload/Upload.ts b/packages/zosfiles/src/methods/upload/Upload.ts index 02c4cc57ae..a7311da3e3 100644 --- a/packages/zosfiles/src/methods/upload/Upload.ts +++ b/packages/zosfiles/src/methods/upload/Upload.ts @@ -481,7 +481,11 @@ export class Upload { const uploadRequest: IRestClientResponse = await ZosmfRestClient.putExpectFullResponse(session, requestOptions); // By default, apiResponse is empty when uploading - const apiResponse: any = {}; + const apiResponse: any = { + success: true, + buffer: fileBuffer, + to: ussname + };; // Return Etag in apiResponse, if requested if (options.returnEtag) { @@ -897,7 +901,6 @@ export class Upload { */ private static get log(): Logger { return Logger.getAppLogger(); - // return Logger.getConsoleLogger(); } @@ -922,7 +925,6 @@ export class Upload { const response: IUploadDir[] = []; if (Upload.hasDirs(dirPath)) { const directories = fs.readdirSync(dirPath).filter((file) => IO.isDir(path.normalize(path.join(dirPath, file)))); - // directories = directories.filter((file) => IO.isDir(path.normalize(path.join(dirPath, file)))); for (let index = 0; index < directories.length; index++) { const dirFullPath = path.normalize(path.join(dirPath, directories[index])); response.push({ From ab2a72e7de7e07e1c29d2810c4383ba70ffa8af4 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Mon, 9 Dec 2024 10:13:59 -0500 Subject: [PATCH 16/61] buffer -> buffer.toString() on apiResponse Signed-off-by: jace-roell --- packages/zosfiles/src/methods/upload/Upload.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/zosfiles/src/methods/upload/Upload.ts b/packages/zosfiles/src/methods/upload/Upload.ts index a7311da3e3..3ddfc6f70b 100644 --- a/packages/zosfiles/src/methods/upload/Upload.ts +++ b/packages/zosfiles/src/methods/upload/Upload.ts @@ -483,7 +483,7 @@ export class Upload { // By default, apiResponse is empty when uploading const apiResponse: any = { success: true, - buffer: fileBuffer, + bufferContents: fileBuffer.toString(), to: ussname };; From 57187569793bbd10fe61bf725827c60a8d3ca284 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Mon, 9 Dec 2024 10:28:39 -0500 Subject: [PATCH 17/61] lint Signed-off-by: jace-roell --- packages/zosfiles/src/methods/upload/Upload.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/zosfiles/src/methods/upload/Upload.ts b/packages/zosfiles/src/methods/upload/Upload.ts index 3ddfc6f70b..0df9ad25a6 100644 --- a/packages/zosfiles/src/methods/upload/Upload.ts +++ b/packages/zosfiles/src/methods/upload/Upload.ts @@ -485,7 +485,7 @@ export class Upload { success: true, bufferContents: fileBuffer.toString(), to: ussname - };; + }; // Return Etag in apiResponse, if requested if (options.returnEtag) { From cdb4f3412e8722b7b42aedfcd31e8690310e9882 Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Tue, 26 Nov 2024 14:42:21 -0500 Subject: [PATCH 18/61] ci: add merge-by workflows Signed-off-by: Trae Yelovich --- .github/workflows/merge-by-comments.yml | 15 +++++++++++++++ .github/workflows/merge-by-table.yml | 25 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 .github/workflows/merge-by-comments.yml create mode 100644 .github/workflows/merge-by-table.yml diff --git a/.github/workflows/merge-by-comments.yml b/.github/workflows/merge-by-comments.yml new file mode 100644 index 0000000000..1f76a66c84 --- /dev/null +++ b/.github/workflows/merge-by-comments.yml @@ -0,0 +1,15 @@ +name: Merge-by + +on: + pull_request: + types: [opened, ready_for_review] +jobs: + rfr_add_date: + name: "Post merge-by date as comment" + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - uses: zowe-actions/shared-actions/merge-by@main + with: + operation: "bump-dates" \ No newline at end of file diff --git a/.github/workflows/merge-by-table.yml b/.github/workflows/merge-by-table.yml new file mode 100644 index 0000000000..8129c44b34 --- /dev/null +++ b/.github/workflows/merge-by-table.yml @@ -0,0 +1,25 @@ +name: Merge-by + +on: + pull_request: + types: [opened, ready_for_review, converted_to_draft] + pull_request_review: + types: [submitted] + push: + branches: + - main + - next + workflow_dispatch: + schedule: + - cron: "0 11 * * *" +jobs: + rfr_add_date: + name: "Build table and notify users" + runs-on: ubuntu-latest + permissions: + discussions: write + pull-requests: write + steps: + - uses: zowe-actions/shared-actions/merge-by@main + with: + operation: "build-table" \ No newline at end of file From 94c52d3e2fa14751c34522b3f74c46b6cf88347a Mon Sep 17 00:00:00 2001 From: jace-roell Date: Mon, 9 Dec 2024 11:04:53 -0500 Subject: [PATCH 19/61] initial commit Signed-off-by: jace-roell --- file.ts | 17 +++++++++++++++++ .../imperative/src/config/src/ProfileInfo.ts | 4 ++++ 2 files changed, 21 insertions(+) create mode 100644 file.ts diff --git a/file.ts b/file.ts new file mode 100644 index 0000000000..f490ca01a2 --- /dev/null +++ b/file.ts @@ -0,0 +1,17 @@ +import { ProfileInfo } from "@zowe/imperative"; +import { GetJobs } from "@zowe/zos-jobs-for-zowe-sdk"; +(async () => { + // Load connection info from default z/OSMF profile + const profInfo = new ProfileInfo("zowe"); + await profInfo.readProfilesFromDisk(); + const zosmfProfAttrs = profInfo.getDefaultProfile("zosmf"); + const zosmfMergedArgs = profInfo.mergeArgsForProfile(zosmfProfAttrs!, { getSecureVals: true }); + const session = ProfileInfo.createSession(zosmfMergedArgs.knownArgs); + const owner: string | undefined = session.ISession.user; + // This may take awhile... + const response = await GetJobs.getJobsByOwner(session, owner!); + console.log(response); +})().catch((err) => { + console.error(err); + process.exit(1); +}); \ No newline at end of file diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index 27119a92b9..dd0c771161 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -597,6 +597,10 @@ export class ProfileInfo { if (osLoc?.global) { layerProperties = this.mLoadedConfig.findLayer(osLoc.user, osLoc.global)?.properties; realBaseProfileName = layerProperties?.defaults.base; + if (!realBaseProfileName && osLoc.user) { + layerProperties = this.mLoadedConfig.findLayer(false, osLoc.global)?.properties; + realBaseProfileName = layerProperties?.defaults.base; + } if (realBaseProfileName) baseProfile = this.mLoadedConfig.api.profiles.buildProfile(realBaseProfileName, layerProperties?.profiles); else baseProfile = null; } From beb94e792f041d7e4ef04689027caeaf3e8c47a0 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Mon, 9 Dec 2024 12:23:35 -0500 Subject: [PATCH 20/61] seperate apiResponse for different PR Signed-off-by: jace-roell --- packages/zosfiles/src/methods/upload/Upload.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/zosfiles/src/methods/upload/Upload.ts b/packages/zosfiles/src/methods/upload/Upload.ts index 0df9ad25a6..2f984ededa 100644 --- a/packages/zosfiles/src/methods/upload/Upload.ts +++ b/packages/zosfiles/src/methods/upload/Upload.ts @@ -481,11 +481,7 @@ export class Upload { const uploadRequest: IRestClientResponse = await ZosmfRestClient.putExpectFullResponse(session, requestOptions); // By default, apiResponse is empty when uploading - const apiResponse: any = { - success: true, - bufferContents: fileBuffer.toString(), - to: ussname - }; + const apiResponse: any = {}; // Return Etag in apiResponse, if requested if (options.returnEtag) { From 95fe387c1e807bede0c309559907ae634115a424 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Mon, 9 Dec 2024 16:38:45 -0500 Subject: [PATCH 21/61] apiResponse Signed-off-by: jace-roell --- .../methods/upload/Upload.unit.test.ts | 2 ++ .../zosfiles/src/methods/upload/Upload.ts | 24 +++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts index 28812678c8..284301aecd 100644 --- a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts +++ b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts @@ -392,6 +392,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeUndefined(); expect(response).toBeDefined(); + expect(response.apiResponse).toMatchObject({"from": "Buffer<>", "success": true, "to": dsName}); expect(zosmfPutFullSpy).toHaveBeenCalledTimes(1); expect(zosmfPutFullSpy).toHaveBeenCalledWith(dummySession, {resource: endpoint, @@ -1755,6 +1756,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeUndefined(); expect(USSresponse).toBeDefined(); + expect(USSresponse.apiResponse).toMatchObject({"from": "Buffer<>", "success": true, "to": dsName}); const normalizedData = ZosFilesUtils.normalizeNewline(data); expect(data.length).not.toBe(normalizedData.length); diff --git a/packages/zosfiles/src/methods/upload/Upload.ts b/packages/zosfiles/src/methods/upload/Upload.ts index 2f984ededa..527b1a3c3b 100644 --- a/packages/zosfiles/src/methods/upload/Upload.ts +++ b/packages/zosfiles/src/methods/upload/Upload.ts @@ -184,7 +184,11 @@ export class Upload { const uploadRequest: IRestClientResponse = await ZosmfRestClient.putExpectFullResponse(session, requestOptions); // By default, apiResponse is empty when uploading - const apiResponse: any = {}; + const apiResponse: any = { + success: true, + from: "Buffer<>", + to: dataSetName + }; // Return Etag in apiResponse, if requested if (options.returnEtag) { @@ -242,7 +246,11 @@ export class Upload { const uploadRequest: IRestClientResponse = await ZosmfRestClient.putExpectFullResponse(session, requestOptions); // By default, apiResponse is empty when uploading - const apiResponse: any = {}; + const apiResponse: any = { + success: true, + from: "Stream<>", + to: dataSetName + }; // Return Etag in apiResponse, if requested if (options.returnEtag) { @@ -481,7 +489,11 @@ export class Upload { const uploadRequest: IRestClientResponse = await ZosmfRestClient.putExpectFullResponse(session, requestOptions); // By default, apiResponse is empty when uploading - const apiResponse: any = {}; + const apiResponse: any = { + success: true, + from: "Buffer<>", + to: ussname + }; // Return Etag in apiResponse, if requested if (options.returnEtag) { @@ -541,7 +553,11 @@ export class Upload { } // By default, apiResponse is empty when uploading - const apiResponse: any = {}; + const apiResponse: any = { + success: true, + from: "Stream<>", + to: ussname + }; // Return Etag in apiResponse, if requested if (options.returnEtag) { From f2aac76da50a49c0cbfc3fa7d602ddaa5c57d0ab Mon Sep 17 00:00:00 2001 From: jace-roell Date: Mon, 9 Dec 2024 16:40:50 -0500 Subject: [PATCH 22/61] changelog Signed-off-by: jace-roell --- packages/zosfiles/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/zosfiles/CHANGELOG.md b/packages/zosfiles/CHANGELOG.md index 4667f7ffce..e9715b05ad 100644 --- a/packages/zosfiles/CHANGELOG.md +++ b/packages/zosfiles/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to the Zowe z/OS files SDK package will be documented in thi ## Recent Changes -- BugFix: Corrected `Upload.BufferToUssFile()` SDK function to properly tag uploaded files. [#2378](https://github.com/zowe/zowe-cli/pull/2378) +- BugFix: Corrected the `Upload.BufferToUssFile()` SDK function to properly tag uploaded files. [#2378](https://github.com/zowe/zowe-cli/pull/2378) ## `8.9.0` From 5153819cea96b347b47a2a24ef6841d809b36ead Mon Sep 17 00:00:00 2001 From: jace-roell Date: Tue, 10 Dec 2024 09:04:29 -0500 Subject: [PATCH 23/61] modify unit tests Signed-off-by: jace-roell --- .../__tests__/__unit__/methods/upload/Upload.unit.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts index 284301aecd..69420591e3 100644 --- a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts +++ b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts @@ -749,6 +749,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeUndefined(); expect(response).toBeDefined(); + expect(response.apiResponse).toMatchObject({"from": "Stream<>", "success": true, "to": dsName}); expect(zosmfPutFullSpy).toHaveBeenCalledTimes(1); expect(zosmfPutFullSpy).toHaveBeenCalledWith(dummySession, {resource: endpoint, @@ -1832,6 +1833,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeUndefined(); expect(USSresponse).toBeDefined(); + expect(USSresponse.apiResponse).toMatchObject({"from": "Stream<>", "success": true, "to": dsName}); expect(USSresponse.success).toBeTruthy(); expect(zosmfExpectFullSpy).toHaveBeenCalledTimes(1); From 981acaaaa3ca600ebb85401a7ad604f8dcdd2e86 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Tue, 10 Dec 2024 10:30:36 -0500 Subject: [PATCH 24/61] system test implementation Signed-off-by: jace-roell --- .../methods/upload/Upload.system.test.ts | 72 ++++++++++++++++++- .../zosfiles/src/methods/upload/Upload.ts | 7 +- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts b/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts index 158729d6ce..121fa142ca 100644 --- a/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts +++ b/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts @@ -19,6 +19,7 @@ import { deleteFiles, getUniqueDatasetName, stripNewLines, wait, waitTime } from import * as fs from "fs"; import { ITestEnvironment } from "../../../../../../__tests__/__src__/environment/ITestEnvironment"; import { runCliScript } from "../../../../../../__tests__/__packages__/cli-test-utils/src"; +import { Readable } from "stream"; let REAL_SESSION: Session; let testEnvironment: ITestEnvironment; @@ -309,6 +310,51 @@ describe("Upload Data Set", () => { } }); + it("should upload a PDS file - bufferToDataSet()", async () => { + let error; + let uploadResponse; + let getResponse; + const data: Buffer = Buffer.from(testdata); + dsname = dsname+("(TEST)"); + + try { + uploadResponse = await Upload.bufferToDataSet(REAL_SESSION, data, dsname); + getResponse = await Get.dataSet(REAL_SESSION, dsname); + } catch (err) { + error = err; + Imperative.console.info("Error: " + inspect(error)); + } + + expect(error).toBeFalsy(); + + expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "Buffer<>","to": dsname}); + expect(Buffer.from(getResponse.toString().trim())).toEqual(data); + }); + + it("should upload a PDS file - streamToDataSet()", async () => { + let error; + let uploadResponse; + let getResponse; + + const inputStream = new Readable(); + inputStream.push(testdata); + inputStream.push(null); + dsname = dsname+("(TEST)"); + + try { + uploadResponse = await Upload.streamToDataSet(REAL_SESSION, inputStream, dsname); + getResponse = await Get.dataSet(REAL_SESSION, dsname); + } catch (err) { + error = err; + Imperative.console.info("Error: " + inspect(error)); + } + + expect(error).toBeFalsy(); + + expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "Stream<>","to": dsname}); + expect(getResponse.toString().trim()).toEqual(testdata); + }); + it("should upload a file to a partitioned data set member using full path", async () => { let error; let response: IZosFilesResponse; @@ -733,7 +779,7 @@ describe("Upload USS file", () => { await deleteFiles(REAL_SESSION, ussname); }); - it("should upload a USS file", async () => { + it("should upload a USS file - bufferToUssFile()", async () => { let error; let uploadResponse; let getResponse; @@ -748,9 +794,33 @@ describe("Upload USS file", () => { } expect(error).toBeFalsy(); + + expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "Buffer<>","to": ussname}); expect(getResponse).toEqual(Buffer.from(data.toString())); + }); + it("should upload a USS file - streamToUssFile()", async () => { + let error; + let uploadResponse; + let getResponse; + const inputStream = new Readable(); + inputStream.push(testdata); + inputStream.push(null); + + try { + uploadResponse = await Upload.streamToUssFile(REAL_SESSION, ussname, inputStream); + getResponse = await Get.USSFile(REAL_SESSION, ussname); + } catch (err) { + error = err; + Imperative.console.info("Error: " + inspect(error)); + } + + expect(error).toBeFalsy(); + + expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "Stream<>","to": ussname}); + expect(getResponse).toEqual(Buffer.from(testdata)); }); + it("should upload a USS file in binary mode", async () => { let error; let uploadResponse; diff --git a/packages/zosfiles/src/methods/upload/Upload.ts b/packages/zosfiles/src/methods/upload/Upload.ts index 527b1a3c3b..7285e91633 100644 --- a/packages/zosfiles/src/methods/upload/Upload.ts +++ b/packages/zosfiles/src/methods/upload/Upload.ts @@ -489,10 +489,11 @@ export class Upload { const uploadRequest: IRestClientResponse = await ZosmfRestClient.putExpectFullResponse(session, requestOptions); // By default, apiResponse is empty when uploading - const apiResponse: any = { + const apiResponse: any = + { success: true, from: "Buffer<>", - to: ussname + to: origUssname }; // Return Etag in apiResponse, if requested @@ -556,7 +557,7 @@ export class Upload { const apiResponse: any = { success: true, from: "Stream<>", - to: ussname + to: origUssname }; // Return Etag in apiResponse, if requested From 4c650d95482c9aa8dd92a0839ba93f5d3a1af5c8 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Tue, 10 Dec 2024 10:59:53 -0500 Subject: [PATCH 25/61] changelog and fix system tests Signed-off-by: jace-roell --- packages/zosfiles/CHANGELOG.md | 1 + .../methods/upload/Upload.system.test.ts | 14 ++++++-------- packages/zosfiles/src/methods/upload/Upload.ts | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/zosfiles/CHANGELOG.md b/packages/zosfiles/CHANGELOG.md index e9715b05ad..33cdb9b9b7 100644 --- a/packages/zosfiles/CHANGELOG.md +++ b/packages/zosfiles/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to the Zowe z/OS files SDK package will be documented in thi ## Recent Changes +- BugFix: Corrected the `apiResponse` response value from `streamToDataSet()`,`streamToUss()`,`bufferToUss()` and `bufferToDataSet()` on the Upload SDK. [#2381](https://github.com/zowe/zowe-cli/pull/2381) - BugFix: Corrected the `Upload.BufferToUssFile()` SDK function to properly tag uploaded files. [#2378](https://github.com/zowe/zowe-cli/pull/2378) ## `8.9.0` diff --git a/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts b/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts index 121fa142ca..adeaa4f699 100644 --- a/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts +++ b/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts @@ -315,11 +315,10 @@ describe("Upload Data Set", () => { let uploadResponse; let getResponse; const data: Buffer = Buffer.from(testdata); - dsname = dsname+("(TEST)"); try { - uploadResponse = await Upload.bufferToDataSet(REAL_SESSION, data, dsname); - getResponse = await Get.dataSet(REAL_SESSION, dsname); + uploadResponse = await Upload.bufferToDataSet(REAL_SESSION, data, dsname+"(TEST)"); + getResponse = await Get.dataSet(REAL_SESSION, dsname+"(TEST)"); } catch (err) { error = err; Imperative.console.info("Error: " + inspect(error)); @@ -327,7 +326,7 @@ describe("Upload Data Set", () => { expect(error).toBeFalsy(); - expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "Buffer<>","to": dsname}); + expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "Buffer<>","to": dsname+"(TEST)"}); expect(Buffer.from(getResponse.toString().trim())).toEqual(data); }); @@ -339,11 +338,10 @@ describe("Upload Data Set", () => { const inputStream = new Readable(); inputStream.push(testdata); inputStream.push(null); - dsname = dsname+("(TEST)"); try { - uploadResponse = await Upload.streamToDataSet(REAL_SESSION, inputStream, dsname); - getResponse = await Get.dataSet(REAL_SESSION, dsname); + uploadResponse = await Upload.streamToDataSet(REAL_SESSION, inputStream, dsname+"(TEST)"); + getResponse = await Get.dataSet(REAL_SESSION, dsname+"(TEST)"); } catch (err) { error = err; Imperative.console.info("Error: " + inspect(error)); @@ -351,7 +349,7 @@ describe("Upload Data Set", () => { expect(error).toBeFalsy(); - expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "Stream<>","to": dsname}); + expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "Stream<>","to": dsname+"(TEST)"}); expect(getResponse.toString().trim()).toEqual(testdata); }); diff --git a/packages/zosfiles/src/methods/upload/Upload.ts b/packages/zosfiles/src/methods/upload/Upload.ts index 7285e91633..4280d80e41 100644 --- a/packages/zosfiles/src/methods/upload/Upload.ts +++ b/packages/zosfiles/src/methods/upload/Upload.ts @@ -489,7 +489,7 @@ export class Upload { const uploadRequest: IRestClientResponse = await ZosmfRestClient.putExpectFullResponse(session, requestOptions); // By default, apiResponse is empty when uploading - const apiResponse: any = + const apiResponse: any = { success: true, from: "Buffer<>", From 00df0a3dd2b002c23af8a4266d631b3d73da85ac Mon Sep 17 00:00:00 2001 From: Rudy Flores <68666202+rudyflores@users.noreply.github.com> Date: Tue, 10 Dec 2024 13:10:57 -0500 Subject: [PATCH 26/61] Attach authentication header to proxy agent Signed-off-by: Rudy Flores <68666202+rudyflores@users.noreply.github.com> --- .../src/rest/src/client/AbstractRestClient.ts | 3 --- .../src/rest/src/client/ProxySettings.ts | 22 +++++++++++++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/imperative/src/rest/src/client/AbstractRestClient.ts b/packages/imperative/src/rest/src/client/AbstractRestClient.ts index 9da363a5cd..c4f908709c 100644 --- a/packages/imperative/src/rest/src/client/AbstractRestClient.ts +++ b/packages/imperative/src/rest/src/client/AbstractRestClient.ts @@ -476,9 +476,6 @@ export abstract class AbstractRestClient { this.mLogger.info(`Proxy setting "${proxyUrl.href}" will not be used as hostname was found listed under "no_proxy" setting.`); } else { this.mLogger.info(`Using the following proxy setting for the request: ${proxyUrl.href}`); - if (this.session.ISession.proxy?.proxy_authorization) { - reqHeaders.push({ 'Proxy-Authorization': this.session.ISession.proxy.proxy_authorization}); - } options.agent = ProxySettings.getProxyAgent(this.session.ISession); } } diff --git a/packages/imperative/src/rest/src/client/ProxySettings.ts b/packages/imperative/src/rest/src/client/ProxySettings.ts index c414003a64..ab0d3ae6d6 100644 --- a/packages/imperative/src/rest/src/client/ProxySettings.ts +++ b/packages/imperative/src/rest/src/client/ProxySettings.ts @@ -45,12 +45,20 @@ export class ProxySettings { */ public static getProxyAgent(session: ISession): Agent | undefined { const proxySetting = this.getProxySettings(session); + const proxyUrl = proxySetting.proxyUrl; + const proxyAuthorizationHeader = proxySetting.authSetting; if (proxySetting?.protocol === HTTP_PROTOCOL) { - return new HttpProxyAgent(proxySetting.proxyUrl); + const proxyAgentOptions = proxyAuthorizationHeader + ? { headers: { 'Proxy-Authorization': proxyAuthorizationHeader } } + : undefined; + return new HttpProxyAgent(proxyUrl, proxyAgentOptions); } if (proxySetting?.protocol === HTTPS_PROTOCOL) { - return new HttpsProxyAgent(proxySetting.proxyUrl, - { rejectUnauthorized: session.rejectUnauthorized ?? true }); + const proxyAgentOptions = { + rejectUnauthorized: session.rejectUnauthorized ?? true, + headers: { 'Proxy-Authorization': proxyAuthorizationHeader } + }; + return new HttpsProxyAgent(proxyUrl, proxyAgentOptions); } } @@ -109,6 +117,11 @@ export class ProxySettings { envVariable = session.proxy?.https_proxy ?? this.getHttpsEnvVariables(); } const proxyUrl = this.checkUrl(envVariable); + + const authSetting = session.proxy?.proxy_authorization; + if (authSetting) { + return {proxyUrl, protocol, authSetting}; + } if (proxyUrl) { return {proxyUrl, protocol}; } @@ -174,5 +187,6 @@ export class ProxySettings { */ interface ProxySetting { proxyUrl: URL, - protocol: HTTP_PROTOCOL_CHOICES + protocol: HTTP_PROTOCOL_CHOICES, + authSetting?: string } From bf6db6be16b14cf136273796e41e229fdca10286 Mon Sep 17 00:00:00 2001 From: Rudy Flores <68666202+rudyflores@users.noreply.github.com> Date: Tue, 10 Dec 2024 13:28:04 -0500 Subject: [PATCH 27/61] Code cleanup Signed-off-by: Rudy Flores <68666202+rudyflores@users.noreply.github.com> --- .../src/rest/src/client/ProxySettings.ts | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/imperative/src/rest/src/client/ProxySettings.ts b/packages/imperative/src/rest/src/client/ProxySettings.ts index ab0d3ae6d6..6132e9e20b 100644 --- a/packages/imperative/src/rest/src/client/ProxySettings.ts +++ b/packages/imperative/src/rest/src/client/ProxySettings.ts @@ -45,20 +45,17 @@ export class ProxySettings { */ public static getProxyAgent(session: ISession): Agent | undefined { const proxySetting = this.getProxySettings(session); - const proxyUrl = proxySetting.proxyUrl; - const proxyAuthorizationHeader = proxySetting.authSetting; + const proxyOptions = {} as ProxyOptions; + const authHeader = ProxySettings.getProxyAuthHeader(proxySetting); + if(authHeader) { + proxyOptions.headers = authHeader; + } if (proxySetting?.protocol === HTTP_PROTOCOL) { - const proxyAgentOptions = proxyAuthorizationHeader - ? { headers: { 'Proxy-Authorization': proxyAuthorizationHeader } } - : undefined; - return new HttpProxyAgent(proxyUrl, proxyAgentOptions); + return new HttpProxyAgent(proxySetting.proxyUrl, proxyOptions); } if (proxySetting?.protocol === HTTPS_PROTOCOL) { - const proxyAgentOptions = { - rejectUnauthorized: session.rejectUnauthorized ?? true, - headers: { 'Proxy-Authorization': proxyAuthorizationHeader } - }; - return new HttpsProxyAgent(proxyUrl, proxyAgentOptions); + proxyOptions.rejectUnauthorized = session.rejectUnauthorized ?? true; + return new HttpsProxyAgent(proxySetting.proxyUrl, proxyOptions); } } @@ -96,6 +93,12 @@ export class ProxySettings { return false; } + private static getProxyAuthHeader(proxySetting: ProxySetting): { [key: string]: string } | undefined { + return proxySetting.authSetting + ? { 'Proxy-Authorization': proxySetting.authSetting } + : undefined; + } + /** * Parses environment variables for proxy servers. * @private @@ -190,3 +193,8 @@ interface ProxySetting { protocol: HTTP_PROTOCOL_CHOICES, authSetting?: string } + +interface ProxyOptions { + headers?: { [key: string]: string }, + rejectUnauthorized?: boolean +} From ad13b8b9f3260414135ff56dd638bcbe0f563069 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Tue, 10 Dec 2024 14:09:03 -0500 Subject: [PATCH 28/61] changelog Signed-off-by: jace-roell --- packages/imperative/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index ded21b7c84..6a407cb842 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the Imperative package will be documented in this file. +## Recent Changes + +- BugFix: Resolved issue where team config base profiles were being overwritten if a user config did not have a base profile. + ## `8.8.3` - BugFix: Modified 8.8.2 bugfix to correct web help alias. [#2361](https://github.com/zowe/zowe-cli/pull/2361) From 1314ffa52cc5fd56061c6a8f4093bdc2c7f86bdd Mon Sep 17 00:00:00 2001 From: jace-roell Date: Tue, 10 Dec 2024 14:13:19 -0500 Subject: [PATCH 29/61] removed test file and changelog fix Signed-off-by: jace-roell --- file.ts | 17 ----------------- packages/imperative/CHANGELOG.md | 2 +- 2 files changed, 1 insertion(+), 18 deletions(-) delete mode 100644 file.ts diff --git a/file.ts b/file.ts deleted file mode 100644 index f490ca01a2..0000000000 --- a/file.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { ProfileInfo } from "@zowe/imperative"; -import { GetJobs } from "@zowe/zos-jobs-for-zowe-sdk"; -(async () => { - // Load connection info from default z/OSMF profile - const profInfo = new ProfileInfo("zowe"); - await profInfo.readProfilesFromDisk(); - const zosmfProfAttrs = profInfo.getDefaultProfile("zosmf"); - const zosmfMergedArgs = profInfo.mergeArgsForProfile(zosmfProfAttrs!, { getSecureVals: true }); - const session = ProfileInfo.createSession(zosmfMergedArgs.knownArgs); - const owner: string | undefined = session.ISession.user; - // This may take awhile... - const response = await GetJobs.getJobsByOwner(session, owner!); - console.log(response); -})().catch((err) => { - console.error(err); - process.exit(1); -}); \ No newline at end of file diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index 6a407cb842..52045f1d05 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to the Imperative package will be documented in this file. ## Recent Changes -- BugFix: Resolved issue where team config base profiles were being overwritten if a user config did not have a base profile. +- BugFix: Resolved issue where team config base profiles were being overwritten if a user config did not have a base profile. [#2383](https://github.com/zowe/zowe-cli/pull/2383) ## `8.8.3` From ba9e5dca58bada99509a5d82e6c2b63d38d7bea5 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Wed, 11 Dec 2024 14:19:43 -0500 Subject: [PATCH 30/61] unit test Signed-off-by: jace-roell --- .../ProfileInfo.TeamConfig.unit.test.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index d4f2aeaf6f..4f0d2b9cac 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -38,6 +38,7 @@ const testEnvPrefix = testAppNm.toUpperCase(); const profileTypes = ["zosmf", "tso", "base", "dummy"]; const testDir = path.join(__dirname, "__resources__"); const teamProjDir = path.join(testDir, testAppNm + "_team_config_proj"); +const teamProjBaseTest = path.join(testDir, testAppNm + "_team_config_proj_base"); function createNewProfInfo(newDir: string, opts?: IProfOpts): ProfileInfo { // create a new ProfileInfo in the desired directory @@ -956,6 +957,37 @@ describe("TeamConfig ProfileInfo tests", () => { expect(caughtError).toBeDefined(); expect(caughtError.message).toContain("Profile attributes must be defined"); }); + it("should fall back to layerProperties when realBaseProfileName is undefined", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk(); + + // Simulate the condition where the active layer has no `defaults.base` but global and user layers exist + const layerActive = profInfo.getTeamConfig().layerActive(); + delete layerActive.properties.defaults.base; + + const globalLayer = profInfo.getTeamConfig().findLayer(false, true); + globalLayer.properties.defaults.base = "globalBaseProfile"; + + const userLayer = profInfo.getTeamConfig().findLayer(true, true); + userLayer.properties.defaults.base = ""; + + const profAttrs = profInfo.getDefaultProfile("zosmf") as IProfAttrs; + + // Merge args to trigger the logic + const mergedArgs = profInfo.mergeArgsForProfile(profAttrs); + + // Expected args should include those from the global base profile + const expectedArgs = [ + {argName: 'host', dataType: 'string', argValue: 'LPAR1.your.domain.net', secure: false}, + {argName: 'port', dataType: 'number', argValue: 1234, secure: false}, + {argName: 'responseFormatHeader', dataType: 'boolean', argValue: true, secure: false} + ]; + + expect(mergedArgs.knownArgs.length).toBeGreaterThanOrEqual(expectedArgs.length); + for (const [idx, arg] of expectedArgs.entries()) { + expect(mergedArgs.knownArgs[idx]).toMatchObject(arg); + } + }); }); describe("mergeArgsForProfileType", () => { From 2e55508d219b4c97584b5959a982e5618b3ec8ca Mon Sep 17 00:00:00 2001 From: anaxceron Date: Wed, 11 Dec 2024 14:50:11 -0500 Subject: [PATCH 31/61] first edits to ReadMe Signed-off-by: anaxceron --- README.md | 137 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 75 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index 1cdeba5a02..1f3e72a83b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# **Zowe CLI** +# Zowe CLI [![codecov](https://codecov.io/gh/zowe/zowe-cli/branch/master/graph/badge.svg)](https://codecov.io/gh/zowe/zowe-cli) [![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7204/badge)](https://bestpractices.coreinfrastructure.org/projects/7204) @@ -8,49 +8,53 @@ This repository also contains the Zowe Node Client SDK. The SDK lets you leverag
-## **Contents** +## Content - [Documentation](#documentation) - - [Contribution Guidelines](#contribution-guidelines) - - [Building Zowe CLI From Source](#building-zowe-cli-from-source) - - [Installing Zowe CLI From Source](#installing-zowe-cli-from-source) + - [Contribution guidelines](#contribution-guidelines) + - [Building Zowe CLI from source](#building-zowe-cli-from-source) + - [Installing Zowe CLI from source](#installing-zowe-cli-from-source) - [Uninstalling Zowe CLI](#uninstalling-zowe-cli) - [Configuring Zowe CLI](#configuring-zowe-cli) - [Zowe Node Client SDK](#zowe-node-client-sdk) - - [Running System Tests](#running-system-tests) + - [Running system tests](#running-system-tests) - [FAQs](#frequently-asked-questions) - - [Project Structure and Governance](#project-structure-and-governance) + - [Project structure and governance](#project-structure-and-governance)
-## **Documentation** -For information about how to install, configure, and use Zowe CLI, see [Zowe CLI Quick Start Documentation](https://docs.zowe.org/stable/getting-started/cli-getting-started/). For more detailed instructions, see [Zowe CLI Documentation](https://docs.zowe.org/stable/user-guide/cli-using-usingcli/), which also includes examples and tutorials for how to contribute to Zowe CLI and develop CLI plug-ins. +## Documentation +For information about how to install, configure, and use Zowe CLI, see [Zowe CLI Quick Start](https://docs.zowe.org/stable/getting-started/cli-getting-started/) documentation. For more detailed instructions, see [Zowe CLI](https://docs.zowe.org/stable/user-guide/cli-using-usingcli/) documentation, which also includes examples and tutorials for how to contribute to Zowe CLI and develop CLI plug-ins. -Engineering design documentation is contained in the 'docs' directory in this repository. To view the Web Help for all Zowe CLI commands and contributed plug-ins, see the [Zowe CLI Web Help](https://docs.zowe.org/stable/web_help/index.html). To view all locally accessible commands, run `zowe --help-web`. For more use cases and tutorials visit [Medium.com/zowe](https://medium.com/zowe). +Engineering design documentation is contained in the `docs` directory in this repository. To view the Web Help for all Zowe CLI commands and contributed plug-ins, see the [Zowe CLI Web Help](https://docs.zowe.org/stable/web_help/index.html). To view all locally accessible commands, run `zowe --help-web`. For more use cases and tutorials visit [Medium.com/zowe](https://medium.com/zowe).
-## **Contribution Guidelines** +## Contribution guidelines The following information is critical to working with the code, running/writing/maintaining automated tests, developing consistent syntax in your plug-in, and ensuring that your plug-in integrates with Zowe CLI properly: -| For more information about ... | See: | +| For more information about | Go to | | ------------------------------ | ----- | -| General guidelines that apply to contributing to Zowe CLI and Plug-ins | [Contribution Guidelines](./CONTRIBUTING.md) | -| Conventions and best practices for creating packages and plug-ins for Zowe CLI | [Package and Plug-in Guidelines](./docs/PackagesAndPluginGuidelines.md)| -Guidelines for contributing to Zowe SDKs| [SDK Guidelines](./docs/SDKGuidelines.md) | -| Guidelines for running tests on Zowe CLI | [Testing Guidelines](./docs/TESTING.md) | -| Guidelines for running tests on the plug-ins that you build| [Plug-in Testing Guidelines](./docs/PluginTESTINGGuidelines.md) | +| General guidelines that apply to contributing to Zowe CLI and Plug-ins | [Contribution guidelines](./CONTRIBUTING.md) | +| Conventions and best practices for creating packages and plug-ins for Zowe CLI | [Package and plug-in guidelines](./docs/PackagesAndPluginGuidelines.md)| +Guidelines for contributing to Zowe SDKs| [SDK guidelines](./docs/SDKGuidelines.md) | +| Guidelines for running tests on Zowe CLI | [Testing guidelines](./docs/TESTING.md) | +| Guidelines for running tests on the plug-ins that you build| [Plug-in testing guidelines](./docs/PluginTESTINGGuidelines.md) | | Documentation that describes the features of the Imperative CLI Framework | [About Imperative CLI Framework](https://github.com/zowe/imperative/wiki) | -| Naming CLI commands and developing syntax | [Command Format Standards](./docs/CommandFormatStandards.md) | -Versioning conventions for Zowe CLI and Plug-ins| [Versioning Guidelines](./docs/MaintainerVersioning.md) | -| Miscellaneous tips for development | [Development Tips](./docs/DevelopmentTips.md) +| Naming CLI commands and developing syntax | [Command format standards](./docs/CommandFormatStandards.md) | +Versioning conventions for Zowe CLI and Plug-ins| [Versioning guidelines](./docs/MaintainerVersioning.md) | +| Miscellaneous tips for development | [Development tips](./docs/DevelopmentTips.md) -**Tip:** -- Visit our [Sample Plug-in repository](https://github.com/zowe/zowe-cli-sample-plugin) for example plug-in code. You can follow developer tutorials [here](https://docs.zowe.org/stable/extend/extend-cli/cli-devTutorials.html). +**Tip:** Visit our [Sample plug-in repository](https://github.com/zowe/zowe-cli-sample-plugin) for example plug-in code. Follow the [developer tutorials](https://docs.zowe.org/stable/extend/extend-cli/cli-devTutorials.html) for more tips.
-## **Building Zowe CLI From Source** -Zowe CLI requires NPM version 8 and Cargo version 1.72.0 (or newer) to build from source. Before proceeding, check your NPM version with `npm --version` and if it's older than 8.x, update with `npm install -g npm`. To check your version of Cargo, run `cargo --version`. Cargo can be installed using rustup: [https://rustup.rs/](https://rustup.rs/). To update Cargo, run the `rustup update` command. +## Building Zowe CLI from source + +Zowe CLI requires NPM version 8 and Cargo version 1.72.0 (or newer) to build from source. + +Check your NPM version with `npm --version` and if it's older than 8.x, update with `npm install -g npm`. + +Check your vCargo version with `cargo --version`. Cargo can be installed using [rustup](https://rustup.rs/). To update Cargo, run the `rustup update` command. For developers using Linux, the following packages are required to build Zowe CLI from source: @@ -80,13 +84,13 @@ When you update `package.json` to include new dependencies, or when you pull cha npm update ``` -**Tip:** -- When necessary, you can run the install command again to update dependencies changed in `package.json`. +**Tip:** When necessary, run the install command again to update dependencies changed in `package.json`.
-## **Installing Zowe CLI From Source** -From your copy of this repository, after a build, navigate to the `packages/cli` directory, then issue the following command to install Zowe CLI from source: +## Installing Zowe CLI from source + +From your copy of this repository, after a build, navigate to the `packages/cli` directory, then install Zowe CLI from source: ``` npm install -g @@ -98,8 +102,8 @@ npm install -g
-## **Uninstalling Zowe CLI** -From your local copy of this repository, issue the following command to uninstall Zowe CLI: +## Uninstalling Zowe CLI +From your local copy of this repository, to uninstall Zowe CLI: ``` npm uninstall --global @zowe/cli @@ -107,49 +111,52 @@ npm uninstall --global @zowe/cli
-## **Configuring Zowe CLI** +## Configuring Zowe CLI -Zowe CLI configuration is made up of different **profiles**. The profiles contain the information that Zowe CLI needs to communicate with the mainframe system. For example, credentials and z/OSMF host name. If you try to use Zowe CLI functionality and you get an error message that Zowe CLI failed to load any profiles, see the `zowe profiles create --help` command for the group of commands that you are trying to use (if any) to initialize your configuration. +Zowe CLI team configuration is made up of different **profiles**. Each profile contains the information that Zowe CLI needs to communicate with the mainframe system, such as credentials and host name. -The most fundamental Zowe CLI profile is a `zosmf` profile. Issue the following command to understand how to create a `zosmf` profile in Zowe CLI: - -``` -zowe profiles create zosmf-profile --help -``` +The most fundamental Zowe CLI profile is a `zosmf` profile, and it is included when Zowe CLI initializes your team configuration. However, you must still add your specific connection information to complete the `zosmf` profile. To do so, update your `~/.zowe/zowe.config.json` configuration file with a text editor or an IDE (such as Visual Studio Code) on your computer. -After you create your profile, you can confirm that the properties of your profile can connect to and communicate with your mainframe system successfully by issuing the following command: +After you create and/or finalize your profile, confirm that the properties of your profile can connect to and communicate with your mainframe system successfully: ``` zowe zosmf check status ``` -For detailed information about creating service profiles, creating base profiles, or integrating with Zowe API ML, see [Using Zowe CLI](https://docs.zowe.org/stable/user-guide/cli-using-usingcli/). +For detailed information about creating profiles, or integrating with Zowe API ML, see the documentation in the [Using Zowe CLI](https://docs.zowe.org/stable/user-guide/cli-using-usingcli/) section of Zowe Docs. -**Tip:** -- When you confirm that your profile connects to and communicates with your mainframe system successfully, you can issue the same command at any time to verify the availability and status of the z/OSMF subsystem on your mainframe. +**Tip:** When you confirm that your profile connects to and communicates with your mainframe system successfully, issue the same command at any time to verify the availability and status of the z/OSMF subsystem on your mainframe.
-## **Zowe Node Client SDK** +## Troubleshooting Zowe CLI + +If you try to use Zowe CLI functionality and you get an error message that Zowe CLI failed to load any profiles, try issuing the following commands: + +- `zowe config edit` to open your `~/.zowe/zowe.config.json` configuration file in your system's default text editor. Fix any properties with incorrect values. +- `zowe config secure` to have Zowe CLI prompt for your secure configuration properties in case your secure values are incorrect in your configuration. +- `zowe config report-env` to generate a report on the status of the key areas in your working environment. Address any problems indicated in the report. + +## Zowe Node Client SDK The Zowe Node Client SDK consists of APIs that enable you to build client applications that interface with the mainframe. Use the APIs to build your own client applications or automation scripts, independent of Zowe CLI. -For information about downloading and getting started with the SDK, see the [Zowe Docs](https://docs.zowe.org/stable/user-guide/sdks-using). To view the Zowe Node.js SDK doc, see [Zowe SDK Docs](https://docs.zowe.org/stable/typedoc/index.html). +For information about downloading and getting started with the SDK, see the [Zowe Docs](https://docs.zowe.org/stable/user-guide/sdks-using). To view the Zowe Node.js SDK doc, see [Using Zowe SDKs](https://docs.zowe.org/stable/typedoc/index.html). -**Tip:** -- Alternatively, you can import Zowe CLI into your project to call the Node APIs. However, importing all of Zowe CLI will increase the size of your project. For example, use the following statement to import packages from Zowe CLI: +Alternatively, import Zowe CLI into your project to call the Node APIs. However, importing all of Zowe CLI increases the size of your project. For example, use the following statement to import packages from Zowe CLI: ``` import { } from @zowe/cli ``` - Where `` is the name of an interface that you populate (i.e. `IIssueParms`) or a function that submits requests (i.e `IssueCommand`). + `` + - Name of an interface that you populate (i.e. `IIssueParms`), or a function that submits requests (i.e `IssueCommand`)
-### Example API Usage +### Example API usage -For example usage syntax, see the readme for each API package in this repository: +For example usage syntax, see the ReadMe for each API package in this repository: - [Provisioning](https://github.com/zowe/zowe-cli/tree/master/packages/provisioning): Provision middleware and resources such as IBM CICS, IBM Db2, IBM MQ, and more. - [z/OS Console](https://github.com/zowe/zowe-cli/tree/master/packages/zosconsole): Perform z/OS console operations. @@ -163,9 +170,11 @@ For example usage syntax, see the readme for each API package in this repository
-## **Running System Tests** +## Running system tests -In addition to Node.js, you must have a means to execute `.sh` (bash) scripts, which are required for running integration tests. On Windows, you can install "Git Bash" (bundled with the standard [Git](https://git-scm.com/downloads) installation - check "Use Git and Unix Tools from Windows Command Prompt" installation option). +In addition to Node.js, you must have a means to execute `.sh` (bash) scripts, which are required for running integration tests. + +On Windows, install "Git Bash", which is bundled with the standard [Git](https://git-scm.com/downloads) installation. Select the installation option **Use Git and Unix Tools from Windows Command Prompt**. After downloading/installing the prerequisites, ensure that you can execute the following commands and receive success responses: @@ -175,11 +184,11 @@ After downloading/installing the prerequisites, ensure that you can execute the 3. On Windows: `where sh` ``` -To run Zowe CLI system tests, you need a configured properties file with proper system information present. +To run Zowe CLI system tests, you need a configured properties file populated with proper system information. -A dummy properties file is present in the `__tests__/__resources__/properties folder`, `default_properties.yaml`. Using this file as a template, you should create a `custom_properties.yaml` file within the same directory. Git is configured to ignore all properties files in the properties folder, except for the `default_properties.yaml` file. If the `custom_properties.yaml` file cannot be found or loaded, an error with relevant details will be thrown when attempting to run tests. +A dummy properties file is available in the `default_properties.yaml` file **[is this correct? I couldn't find it in the repo]** in the `__tests__/__resources__/properties` folder. Using this file as a template, you should create a `custom_properties.yaml` file within the same directory. Git is configured to ignore all properties files in the properties folder, except for the `default_properties.yaml` **[is this correct? I couldn't find it in the repo]** file. If the `custom_properties.yaml` file cannot be found or loaded, an error with relevant details displays when attempting to run tests. -You can then run the system tests by issuing the following command: +Run the system tests: ``` npm run test:system @@ -187,34 +196,38 @@ npm run test:system
-**IMPORTANT!** Do not commit configured properties files because they contain security principles and other critical information. +**IMPORTANT!** Do not commit configured properties files to your repository **[is "to your repo" correct here?]** because they contain security principles and other critical information.
-## **Frequently Asked Questions** +## **Frequently asked questions** -**How can I install Zowe CLI as a root user on Mac/Linux?** +### How can I install Zowe CLI as a root user on Mac/Linux? - - You can install the CLI as root so that all users can access the CLI without installing it individually on their user account. As the root user on Mac/Linux, issue the following command: + - Install the CLI as root so that all users can access the CLI without installing it individually on their user account. As the root user on Mac/Linux, issue the following command: ``` npm i -g @zowe/cli@latest --ignore-scripts ``` **WARNING!** If you use this method, plug-ins that are installed as root can only be accessed as root. Users must install plug-ins on their user account or share all profiles/plugins/settings/logs with root. You also might encounter npm errors if you install as root. We recommend that Linux administrators implement a user/group environment where permissions can be more carefully controlled. -**What is the difference between V1 and V2?** +### What is the difference between Zowe V2 and V3? + + - V3 deprecates support for Zowe V1 profiles. + + - To updgrade from an older Zowe release, see [Migrating from Zowe Vx to Zowe V3](https://docs.zowe.org/stable/whats-new/zowe-v3-migratio3). - - V2 uses **team profiles** and **deprecates the Secure Credential Store** (SCS) plug-in. + - V2 uses **team profiles** and **deprecates the Secure Credential Store** (SCS) plug-in used in Zowe V1. - Connection details can be managed efficiently within one file, promoting a global configuration that can be shared across teams and mainframe services. For more information on how to use profiles, visit [Zowe Docs](https://docs.zowe.org/stable/user-guide/cli-using-using-team-profiles/). + - Connection details can be managed efficiently within one file, promoting a global configuration that can be shared across teams and mainframe services. For more information on how to use profiles, see [Team configurations](https://docs.zowe.org/stable/user-guide/cli-using-using-team-profiles/) in Zowe Docs. - Secure credential encryption is included in the core CLI. + - Secure credential encryption is included in the core CLI.
Don't see what you're looking for? Browse questions from the community or ask your own in the [Q&A section](https://github.com/zowe/zowe-cli/discussions/categories/q-a) of our repo. -## **Project Structure and Governance** +## **Project structure and governance** Zowe CLI is a component of the Zowe Open Mainframe Project, part of the Linux Foundation. From cd8057014b12d72c94cebd3262be1b1f21b871d5 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Thu, 12 Dec 2024 07:30:48 -0500 Subject: [PATCH 32/61] unused var Signed-off-by: jace-roell --- .../src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index 4f0d2b9cac..f6c599ee2e 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -38,7 +38,6 @@ const testEnvPrefix = testAppNm.toUpperCase(); const profileTypes = ["zosmf", "tso", "base", "dummy"]; const testDir = path.join(__dirname, "__resources__"); const teamProjDir = path.join(testDir, testAppNm + "_team_config_proj"); -const teamProjBaseTest = path.join(testDir, testAppNm + "_team_config_proj_base"); function createNewProfInfo(newDir: string, opts?: IProfOpts): ProfileInfo { // create a new ProfileInfo in the desired directory From a24a5511b8928e9ba265ab5b67bca162dc4e671e Mon Sep 17 00:00:00 2001 From: jace-roell Date: Thu, 12 Dec 2024 08:59:20 -0500 Subject: [PATCH 33/61] coverage and proper mocking Signed-off-by: jace-roell --- .../config/__tests__/ProfileInfo.TeamConfig.unit.test.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index f6c599ee2e..b28ccd720f 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -32,6 +32,7 @@ import { ConfigProfiles } from "../src/api"; import { IExtendersJsonOpts } from "../src/doc/IExtenderOpts"; import { ConfigSchema } from "../src/ConfigSchema"; import { Logger } from "../../logger/src/Logger"; +import { IProfLocOsLoc } from "@zowe/imperative"; const testAppNm = "ProfInfoApp"; const testEnvPrefix = testAppNm.toUpperCase(); @@ -960,6 +961,14 @@ describe("TeamConfig ProfileInfo tests", () => { const profInfo = createNewProfInfo(teamProjDir); await profInfo.readProfilesFromDisk(); + const mockResp: IProfLocOsLoc[] = [{ + global: true, + name: "LPAR1", + path: "/mocked/path/xyz", + user: true + }]; + jest.spyOn(ProfileInfo.prototype, "getOsLocInfo").mockReturnValue(mockResp); + // Simulate the condition where the active layer has no `defaults.base` but global and user layers exist const layerActive = profInfo.getTeamConfig().layerActive(); delete layerActive.properties.defaults.base; From 4c7779452e8fbf8d41a83b9b4f95a427161e4ce7 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Thu, 12 Dec 2024 09:29:11 -0500 Subject: [PATCH 34/61] consolidated code Signed-off-by: jace-roell --- .../config/__tests__/ProfileInfo.TeamConfig.unit.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index b28ccd720f..1ed8dd659d 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -32,7 +32,6 @@ import { ConfigProfiles } from "../src/api"; import { IExtendersJsonOpts } from "../src/doc/IExtenderOpts"; import { ConfigSchema } from "../src/ConfigSchema"; import { Logger } from "../../logger/src/Logger"; -import { IProfLocOsLoc } from "@zowe/imperative"; const testAppNm = "ProfInfoApp"; const testEnvPrefix = testAppNm.toUpperCase(); @@ -961,13 +960,12 @@ describe("TeamConfig ProfileInfo tests", () => { const profInfo = createNewProfInfo(teamProjDir); await profInfo.readProfilesFromDisk(); - const mockResp: IProfLocOsLoc[] = [{ + jest.spyOn(ProfileInfo.prototype, "getOsLocInfo").mockReturnValue([{ global: true, name: "LPAR1", path: "/mocked/path/xyz", user: true - }]; - jest.spyOn(ProfileInfo.prototype, "getOsLocInfo").mockReturnValue(mockResp); + }]); // Simulate the condition where the active layer has no `defaults.base` but global and user layers exist const layerActive = profInfo.getTeamConfig().layerActive(); From 4687ae8e40374bf42aba68955a01ec508813388d Mon Sep 17 00:00:00 2001 From: anaxceron Date: Thu, 12 Dec 2024 14:16:22 -0500 Subject: [PATCH 35/61] removing file name question Signed-off-by: anaxceron --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f3e72a83b..9e650b2d4f 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,7 @@ Alternatively, import Zowe CLI into your project to call the Node APIs. However, ``` `` + - Name of an interface that you populate (i.e. `IIssueParms`), or a function that submits requests (i.e `IssueCommand`)
@@ -186,7 +187,7 @@ After downloading/installing the prerequisites, ensure that you can execute the To run Zowe CLI system tests, you need a configured properties file populated with proper system information. -A dummy properties file is available in the `default_properties.yaml` file **[is this correct? I couldn't find it in the repo]** in the `__tests__/__resources__/properties` folder. Using this file as a template, you should create a `custom_properties.yaml` file within the same directory. Git is configured to ignore all properties files in the properties folder, except for the `default_properties.yaml` **[is this correct? I couldn't find it in the repo]** file. If the `custom_properties.yaml` file cannot be found or loaded, an error with relevant details displays when attempting to run tests. +A dummy properties file is available in the `default_properties.yaml` file in the `__tests__/__resources__/properties` folder. Using this file as a template, you should create a `custom_properties.yaml` file within the same directory. Git is configured to ignore all properties files in the properties folder, except for the `default_properties.yaml` file. If the `custom_properties.yaml` file cannot be found or loaded, an error with relevant details displays when attempting to run tests. Run the system tests: @@ -209,6 +210,7 @@ npm run test:system ``` npm i -g @zowe/cli@latest --ignore-scripts ``` + **WARNING!** If you use this method, plug-ins that are installed as root can only be accessed as root. Users must install plug-ins on their user account or share all profiles/plugins/settings/logs with root. You also might encounter npm errors if you install as root. We recommend that Linux administrators implement a user/group environment where permissions can be more carefully controlled. ### What is the difference between Zowe V2 and V3? From 8760c26c19653b549e476960390a6d06f768d39b Mon Sep 17 00:00:00 2001 From: anaxceron Date: Thu, 12 Dec 2024 14:19:42 -0500 Subject: [PATCH 36/61] fixing formatting Signed-off-by: anaxceron --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9e650b2d4f..dc751cc189 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Zowe CLI + [![codecov](https://codecov.io/gh/zowe/zowe-cli/branch/master/graph/badge.svg)](https://codecov.io/gh/zowe/zowe-cli) [![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7204/badge)](https://bestpractices.coreinfrastructure.org/projects/7204) @@ -9,6 +10,7 @@ This repository also contains the Zowe Node Client SDK. The SDK lets you leverag
## Content + - [Documentation](#documentation) - [Contribution guidelines](#contribution-guidelines) - [Building Zowe CLI from source](#building-zowe-cli-from-source) @@ -23,6 +25,7 @@ This repository also contains the Zowe Node Client SDK. The SDK lets you leverag
## Documentation + For information about how to install, configure, and use Zowe CLI, see [Zowe CLI Quick Start](https://docs.zowe.org/stable/getting-started/cli-getting-started/) documentation. For more detailed instructions, see [Zowe CLI](https://docs.zowe.org/stable/user-guide/cli-using-usingcli/) documentation, which also includes examples and tutorials for how to contribute to Zowe CLI and develop CLI plug-ins. Engineering design documentation is contained in the `docs` directory in this repository. To view the Web Help for all Zowe CLI commands and contributed plug-ins, see the [Zowe CLI Web Help](https://docs.zowe.org/stable/web_help/index.html). To view all locally accessible commands, run `zowe --help-web`. For more use cases and tutorials visit [Medium.com/zowe](https://medium.com/zowe). @@ -30,6 +33,7 @@ Engineering design documentation is contained in the `docs` directory in this re
## Contribution guidelines + The following information is critical to working with the code, running/writing/maintaining automated tests, developing consistent syntax in your plug-in, and ensuring that your plug-in integrates with Zowe CLI properly: | For more information about | Go to | @@ -96,13 +100,15 @@ From your copy of this repository, after a build, navigate to the `packages/cli` npm install -g ``` -**Notes:** +**Notes:** + - Depending on how you configured npm on Linux or Mac, you might need to prefix the `npm install -g` command or the `npm uninstall -g` command with `sudo` to let npm have write access to the installation directory. - On Windows, the `npm install -g` command might fail several times due to an `EPERM` error. This appears to be a bug that npm documented in their GitHub issues. This behaviour does not appear to be specific to installing the Zowe CLI package. Unfortunately, the only solution that we know of is to issue the `npm cache clean` command and the `npm install -g` command repeatedly until it works.
## Uninstalling Zowe CLI + From your local copy of this repository, to uninstall Zowe CLI: ``` @@ -150,7 +156,7 @@ Alternatively, import Zowe CLI into your project to call the Node APIs. However, ``` `` - + - Name of an interface that you populate (i.e. `IIssueParms`), or a function that submits requests (i.e `IssueCommand`)
@@ -201,7 +207,7 @@ npm run test:system
-## **Frequently asked questions** +## Frequently asked questions ### How can I install Zowe CLI as a root user on Mac/Linux? @@ -229,7 +235,7 @@ npm run test:system Don't see what you're looking for? Browse questions from the community or ask your own in the [Q&A section](https://github.com/zowe/zowe-cli/discussions/categories/q-a) of our repo. -## **Project structure and governance** +## Project structure and governance Zowe CLI is a component of the Zowe Open Mainframe Project, part of the Linux Foundation. From 39b8da2d8cbfcaf002c74e38de0202a673997720 Mon Sep 17 00:00:00 2001 From: anaxceron Date: Thu, 12 Dec 2024 14:23:32 -0500 Subject: [PATCH 37/61] editing "important" message per review feedback Signed-off-by: anaxceron --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dc751cc189..ca07245ec6 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ npm run test:system
-**IMPORTANT!** Do not commit configured properties files to your repository **[is "to your repo" correct here?]** because they contain security principles and other critical information. +**IMPORTANT!** Do not commit configured properties files to this repository because they contain security principles and other critical information.
From bcad1ab9c37411536dd3edb423ea8781d9154016 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Fri, 13 Dec 2024 12:08:39 -0500 Subject: [PATCH 38/61] Move AuthOrder prototype into 'prototypes' directory Signed-off-by: Gene Johnston --- prototypes/Readme.md | 7 + prototypes/packages/.gitkeep | 0 .../src/zosfiles/list/ds/DataSet.handler.ts | 47 ++ .../cli/src/zosfiles/list/ds/Readme.md | 7 + .../src/rest/src/session/AuthOrder.ts | 316 ++++++++++ .../src/session/ConnectionPropsForSessCfg.ts | 569 ++++++++++++++++++ .../imperative/src/rest/src/session/Readme.md | 7 + 7 files changed, 953 insertions(+) create mode 100644 prototypes/Readme.md create mode 100644 prototypes/packages/.gitkeep create mode 100644 prototypes/packages/cli/src/zosfiles/list/ds/DataSet.handler.ts create mode 100644 prototypes/packages/cli/src/zosfiles/list/ds/Readme.md create mode 100644 prototypes/packages/imperative/src/rest/src/session/AuthOrder.ts create mode 100644 prototypes/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts create mode 100644 prototypes/packages/imperative/src/rest/src/session/Readme.md diff --git a/prototypes/Readme.md b/prototypes/Readme.md new file mode 100644 index 0000000000..a8121f6ec7 --- /dev/null +++ b/prototypes/Readme.md @@ -0,0 +1,7 @@ +The purpose of this **prototypes** folder is to provide a home for prototype or proof-of-concept code. As an example, new, experimental code that implements a compelling feature may be good model for the future permanent implementation of that feature. + +During experiments, you might place a new class into a particular package to confirm that an idea is feasible. However, that code may not be complete enough to be built and packaged into the product. Lint rules might fail on this new code. You may not have any tests yet, so code coverage verification may fail. + +You do not want this new code to cause Zowe build pipelines to fail, but you do not want to lose the useful work that has been completed. Placing your source file(s) under the **prototypes** directory is a way to keep your valuable experiment and not break the Zowe build process. + +Place your source file into a path under the **prototypes** directory that mirrors the real directory path . Personally, I like to create a hard link from the file in my real file path to an identical file path under the **prototypes** directory. That way I can import, compile, and debug in the real directory until I complete experiments. Before committing, I can just delete the file in the real directory path and the remaining hard-linked file in the **prototypes** directory path will have all of the latest changes. diff --git a/prototypes/packages/.gitkeep b/prototypes/packages/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prototypes/packages/cli/src/zosfiles/list/ds/DataSet.handler.ts b/prototypes/packages/cli/src/zosfiles/list/ds/DataSet.handler.ts new file mode 100644 index 0000000000..e918eb5e8a --- /dev/null +++ b/prototypes/packages/cli/src/zosfiles/list/ds/DataSet.handler.ts @@ -0,0 +1,47 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { AbstractSession, IHandlerParameters, TextUtils } from "@zowe/imperative"; +import { IZosFilesResponse, List } from "@zowe/zos-files-for-zowe-sdk"; +import { ZosFilesBaseHandler } from "../../ZosFilesBase.handler"; + +/** + * Handler to list a data sets + * @export + */ +export default class DataSetHandler extends ZosFilesBaseHandler { + public async processWithSession(commandParameters: IHandlerParameters, session: AbstractSession): Promise { + /* todo: Remove diagnostic print statements + */ + return { + commandResponse: "____ DataSetHandler: Pretend that we ran the list command.", + success: true + }; + // end Remove todo: */ + + const response = await List.dataSet(session, commandParameters.arguments.dataSetName, { + volume: commandParameters.arguments.volumeSerial, + attributes: commandParameters.arguments.attributes, + maxLength: commandParameters.arguments.maxLength, + responseTimeout: commandParameters.arguments.responseTimeout, + start: commandParameters.arguments.start + }); + + if (commandParameters.arguments.attributes && response.apiResponse.items.length > 0) { + commandParameters.response.console.log(TextUtils.prettyJson(response.apiResponse.items)); + } else { + const dsnameList = response.apiResponse.items.map((mem: any) => mem.dsname); + commandParameters.response.console.log(dsnameList.join("\n")); + } + + return response; + } +} diff --git a/prototypes/packages/cli/src/zosfiles/list/ds/Readme.md b/prototypes/packages/cli/src/zosfiles/list/ds/Readme.md new file mode 100644 index 0000000000..5a1554004d --- /dev/null +++ b/prototypes/packages/cli/src/zosfiles/list/ds/Readme.md @@ -0,0 +1,7 @@ +Files used to create a prototype of AuthOrder are: + +prototypes\packages\imperative\src\rest\src\session\AuthOrder.ts + +prototypes\packages\imperative\src\rest\src\session\ConnectionPropsForSessCfg.ts + +prototypes\packages\cli\src\zosfiles\list\ds\DataSet.handler.ts diff --git a/prototypes/packages/imperative/src/rest/src/session/AuthOrder.ts b/prototypes/packages/imperative/src/rest/src/session/AuthOrder.ts new file mode 100644 index 0000000000..dade7829d5 --- /dev/null +++ b/prototypes/packages/imperative/src/rest/src/session/AuthOrder.ts @@ -0,0 +1,316 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ICommandArguments } from "../../../cmd"; +import { ImperativeError } from "../../../error"; +import { ISession } from "./doc/ISession"; +import { Logger } from "../../../logger"; +import * as SessConstants from "./SessConstants"; + +/** + * @internal - Cannot be used outside of the imperative package + * + * The purpose of this class is to detect an authentication order property + * supplied by a user in a profile, command line, or environment variable. + * That authOrder is then used to place the correct set of credentials into + * a session for authentication. + */ +export class AuthOrder { + + /** + * When a user does not supply an auth order, Zowe clients will use a + * hard-coded default order. This property records whether AUTH_TYPE_BASIC + * or AUTH_TYPE_TOKEN is the top auth choice in the order. + */ + private static m_topDefaultAuth: string = SessConstants.AUTH_TYPE_BASIC; + + /** + * This array of authentication types specifies the order of preferred + * authentication. It contains the user-specified order, or a default order + * if the user does not specify an order. m_authOrder[0] is the highest + * preferred authentication. + */ + private static m_authOrder: SessConstants.AUTH_TYPE_CHOICES[] = null; + + // *********************************************************************** + /** + * Set the top auth type when a default authOrder is used. Previously, + * two different hard-coded orders were present in the Zowe clients. + * Both hard-coded orders are now provided by this class. Zowe code, + * that still sets a specific order for backward compatibility, now + * calls this function to ensure that that the original behavior remains + * the same and avoids a breaking change when a user has not specified + * an authOrder property. + * + * @param topDefaultAuth - Input. + * The top authentication type that will be used when forming a + * default authOrder. + */ + public static setTopDefaultAuth( + topDefaultAuth: typeof SessConstants.AUTH_TYPE_BASIC | typeof SessConstants.AUTH_TYPE_TOKEN + ): void { + AuthOrder.m_topDefaultAuth = topDefaultAuth; + } + + // *********************************************************************** + /** + * Cache the authOrder property from the supplied cmdArgs. If no authOrder exists + * in cmdArgs, a default authOrder is created and cached. + * + * @param cmdArgs - Input. + * The set of arguments that the calling function is using. + */ + private static cacheAuthOrder(cmdArgs: ICommandArguments): void { + // have we already cached the authOrder? + if (AuthOrder.m_authOrder !== null) { + // start over with an empty order. + AuthOrder.m_authOrder = null; + } + + if (cmdArgs.authOrder) { + // validate each user-supplied type of authentication + for (const nextUserAuth of cmdArgs.authOrder) { + switch (nextUserAuth) { + case SessConstants.AUTH_TYPE_BASIC: + case SessConstants.AUTH_TYPE_TOKEN: + case SessConstants.AUTH_TYPE_BEARER: + case SessConstants.AUTH_TYPE_CERT_PEM: + case SessConstants.AUTH_TYPE_NONE: + if (AuthOrder.m_authOrder === null) { + AuthOrder.m_authOrder = []; + } + AuthOrder.m_authOrder.push(nextUserAuth); + break; + default: + Logger.getImperativeLogger().error( + `The authentication = '${nextUserAuth}' is not valid and will be ignored.` + ); + // todo: Remove diagnostic print statements + console.log("____ cacheAuthOrder: nextUserAuth = '" + nextUserAuth + "' is not valid and will be ignored."); + // todo: end Remove + } + } + } + + // the user supplied an authOrder + if (AuthOrder.m_authOrder !== null) { + return; + } + + // No authOrder was supplied by the user. Create a default order. + AuthOrder.m_authOrder = []; + if (AuthOrder.m_topDefaultAuth === SessConstants.AUTH_TYPE_BASIC) { + // we want user & password auth as the top choice + AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_BASIC); + AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_TOKEN); + } else { + // we want token auth as the top choice + AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_TOKEN); + AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_BASIC); + } + // add remaining auth types. We do not include 'none' in our defaults. + AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_BEARER); + AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_CERT_PEM); + } + + // *********************************************************************** + /** + * Find the highest auth type (according to the authOrder) which exists + * in either the supplied session config or command line arguments. + * Then place the credentials associated with that auth type into the + * supplied session config. Credentials for all other auth types are + * removed from the session config. + * + * @param sessCfg - Modified. + * Authentication properties are added to and removed from this + * session configuration, which can already have properties in + * this object when passed to this function. + * + * @param cmdArgs - Input. + * The set of arguments with which the calling function is operating. + * For CLI, the cmdArgs come from the command line, profile, or + * environment. Other apps can place relevant arguments into this + * object to be processed by this function. + */ + public static putTopAuthInSession( + sessCfg: SessCfgType, + cmdArgs: ICommandArguments + ): void { + let sessTypeToUse: SessConstants.AUTH_TYPE_CHOICES = null; + + // todo: Remove diagnostic print statements + console.log("____ putTopAuthInSession: cmdArgs = " + JSON.stringify(cmdArgs, null, 2)); + sessCfg.tokenType = "apimlAuthenticationToken"; + sessCfg.tokenValue = "SomeTokenValue"; + sessCfg.cert = "./certFile.txt"; + sessCfg.certKey = "./certKeyFile.txt"; + sessCfg.authTypeOrder = []; + sessCfg.authTypeOrder.push("bogusAuthType1"); + sessCfg.authTypeOrder.push("bogusAuthType2"); + sessCfg.authTypeOrder.push("bogusAuthType3"); + sessCfg.authTypeOrder.push("bogusAuthType4"); + console.log("____ putTopAuthInSession: sessCfg before processing = " + JSON.stringify(sessCfg, null, 2)); + // todo: end Remove + + // cache the correct authOrder to use + AuthOrder.cacheAuthOrder(cmdArgs); + + // Detect the first auth type (from our auth order) provided in the session config or in command args. + // Ensure that the auth properties are placed in the session config. + // Record the detected auth type for use as the session type. + let errMsg: string; + for (const nextAuth of AuthOrder.m_authOrder) { + switch (nextAuth) { + case SessConstants.AUTH_TYPE_BASIC: + // todo: do we have to check for sessCfg.base64EncodedAuth ? + if (cmdArgs.user?.length > 0) { + sessCfg.user = cmdArgs.user; + } + if (cmdArgs.password?.length > 0) { + sessCfg.password = cmdArgs.password; + } + if (sessCfg.user?.length > 0 && sessCfg.password?.length > 0) { + // TODO: Confirm in ConnectionPropsForSessCfg that requestToken will work ok with sessTypeToUse + sessTypeToUse = SessConstants.AUTH_TYPE_BASIC; + } + break; + case SessConstants.AUTH_TYPE_TOKEN: + if (cmdArgs.tokenType?.length > 0) { + sessCfg.tokenType = cmdArgs.tokenType; + } + if (cmdArgs.tokenValue?.length > 0) { + sessCfg.tokenValue = cmdArgs.tokenValue; + } + if (sessCfg.tokenType?.length > 0 && sessCfg.tokenValue?.length > 0) { + sessTypeToUse = SessConstants.AUTH_TYPE_TOKEN; + } + break; + case SessConstants.AUTH_TYPE_BEARER: + if (cmdArgs.tokenType?.length > 0) { + sessCfg.tokenType = cmdArgs.tokenType; + } + if (cmdArgs.tokenValue?.length > 0) { + sessCfg.tokenValue = cmdArgs.tokenValue; + } + // a tokenValue with no tokenType implies a bearer token + if (!(sessCfg.tokenType?.length > 0) && sessCfg.tokenValue?.length > 0) { + sessTypeToUse = SessConstants.AUTH_TYPE_BEARER; + } + break; + case SessConstants.AUTH_TYPE_CERT_PEM: + if (cmdArgs.certFile?.length > 0) { + sessCfg.cert = cmdArgs.certFile; + } + if (cmdArgs.certKeyFile?.length > 0) { + sessCfg.certKey = cmdArgs.certKeyFile; + } + if (sessCfg.cert?.length > 0 && sessCfg.certKey?.length > 0) { + sessTypeToUse = SessConstants.AUTH_TYPE_CERT_PEM; + } + break; + case SessConstants.AUTH_TYPE_NONE: + sessTypeToUse = SessConstants.AUTH_TYPE_NONE; + break; + default: + // authOrder was validated. A wrong value now is our programming error. + errMsg = `authOrder contains an invalid authentication = ${nextAuth}.`; + Logger.getImperativeLogger().error(errMsg); + throw new ImperativeError({ msg: errMsg }); + } + if (sessTypeToUse !== null) { + // stop looking for auth types after we find the first one + break; + } + } + + // When no creds are in the session and AUTH_TYPE_NONE is not in the user's authOrder, + // remove the session type from the session. Otherwise set the type that we found. + if (sessTypeToUse === null) { + delete sessCfg.type; + } else { + sessCfg.type = sessTypeToUse; + } + + // remove all extra auth creds from the session + AuthOrder.removeExtraCredsFromSess(sessCfg); + + // copy our authOrder into the session object + sessCfg.authTypeOrder = [...AuthOrder.m_authOrder]; + + // todo: Should we throw error if no creds are in the session, or let other functions throw the error? + + // todo: Remove diagnostic print statements + console.log("____ putTopAuthInSession:\nsessCfg after processing = " + JSON.stringify(sessCfg, null, 2)); + // todo: end Remove + } + + // *********************************************************************** + /** + * Remove all credential properties from the supplied session except for the + * creds related to the session type specified within the sessCfg argument. + * + * @param sessCfg - Modified. + * Authentication credentials are removed from this session configuration. + */ + private static removeExtraCredsFromSess( + sessCfg: SessCfgType + ): void { + if (AuthOrder.cacheAuthOrder == null) { + const errMsg = "AuthOrder.cacheAuthOrder must be called before AuthOrder.removeExtraCredsFromSess"; + Logger.getImperativeLogger().error(errMsg); + throw new ImperativeError({ msg: errMsg }); + } + if (!sessCfg?.type) { + const errMsg = "Session type must exist in the supplied session."; + Logger.getImperativeLogger().error(errMsg); + throw new ImperativeError({ msg: errMsg }); + } + + // initially set all creds to be removed from the session. Later we delete the desired creds from this set + const credsToRemove = new Set(["user", "password", "base64EncodedAuth", "tokenType", "tokenValue", "cert", "certKey"]); + + // Delete the selected creds from the set of creds that will be removed from our session config. + let errMsg: string; + switch (sessCfg.type) { + case SessConstants.AUTH_TYPE_BASIC: + credsToRemove.delete("user"); + credsToRemove.delete("password"); + credsToRemove.delete("base64EncodedAuth"); + break; + case SessConstants.AUTH_TYPE_TOKEN: + credsToRemove.delete("tokenType"); + credsToRemove.delete("tokenValue"); + break; + case SessConstants.AUTH_TYPE_BEARER: + credsToRemove.delete("tokenValue"); + break; + case SessConstants.AUTH_TYPE_CERT_PEM: + credsToRemove.delete("cert"); + credsToRemove.delete("certKey"); + break; + case SessConstants.AUTH_TYPE_NONE: + break; + default: + // authOrder was validated. A wrong value now is our programming error. + errMsg = `Session an invalid type = ${sessCfg.type}.`; + Logger.getImperativeLogger().error(errMsg); + throw new ImperativeError({ msg: errMsg }); + } + + // remove all auth creds from the session, except the creds for the auth type that we chose to keep + const credIter = credsToRemove.values(); + let nextCredToRemove = credIter.next(); + while (!nextCredToRemove.done) { + delete (sessCfg as any)[nextCredToRemove.value]; + nextCredToRemove = credIter.next(); + } + } +} \ No newline at end of file diff --git a/prototypes/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts b/prototypes/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts new file mode 100644 index 0000000000..76ea99871b --- /dev/null +++ b/prototypes/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts @@ -0,0 +1,569 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { CliUtils, ImperativeConfig, TextUtils } from "../../../utilities"; +import { ICommandArguments, IHandlerParameters } from "../../../cmd"; +import { ImperativeError } from "../../../error"; +import { IOptionsForAddConnProps } from "./doc/IOptionsForAddConnProps"; +import { Logger } from "../../../logger"; +import * as SessConstants from "./SessConstants"; +import { IPromptOptions } from "../../../cmd/src/doc/response/api/handler/IPromptOptions"; +import { ISession } from "./doc/ISession"; +import { IProfileProperty } from "../../../profiles"; +import { ConfigAutoStore } from "../../../config/src/ConfigAutoStore"; +import { ConfigUtils } from "../../../config/src/ConfigUtils"; +import { AuthOrder } from "./AuthOrder"; + +/** + * Extend options for IPromptOptions for internal wrapper method + * @interface IHandlePromptOptions + * @extends {IPromptOptions} + */ +interface IHandlePromptOptions extends IPromptOptions { + + /** + * Adds IHandlerParameters to IPromptOptions + * @type {IHandlerParameters} + * @memberof IHandlePromptOptions + */ + parms?: IHandlerParameters; +} + +/** + * This class adds connection information to an existing session configuration + * object for making REST API calls with the Imperative RestClient. + */ +export class ConnectionPropsForSessCfg { + + // *********************************************************************** + /** + * Create a REST session configuration object starting with the supplied + * initialSessCfg and retrieving connection properties from the command + * line arguments (or environment, or profile). If required connection + * properties are missing we interactively prompt the user for the values. + * for any of the following properties: + * host + * port + * user name + * password + * + * Any prompt will timeout after 30 seconds so that this function can + * be run from an automated script, and will not indefinitely hang that + * script. + * + * In addition to properties that we prompt for, we will also add the following + * properties to the session configuration if they are available. + * type + * tokenType + * tokenValue + * + * @param initialSessCfg + * An initial session configuration (like ISession, or other + * specially defined configuration) that contains your desired + * session configuration properties. + * + * @param cmdArgs + * The arguments specified by the user on the command line + * (or in environment, or in profile). The contents of the + * supplied cmdArgs will be modified. + * + * @param connOpts + * Options that alter our connection actions. See IOptionsForAddConnProps. + * The connOpts parameter need not be supplied. + * + * @example + * // Within the process() function of a command handler, + * // do steps similar to the following: + * const sessCfg: ISession = { + * rejectUnauthorized: commandParameters.arguments.rejectUnauthorized, + * basePath: commandParameters.arguments.basePath + * }; + * const connectableSessCfg = await ConnectionPropsForSessCfg.addPropsOrPrompt( + * sessCfg, commandParameters.arguments + * ); + * mySession = new Session(connectableSessCfg); + * + * @returns A session configuration object with connection information + * added to the initialSessCfg. Its intended use is for our + * caller to create a session for a REST Client. + */ + public static async addPropsOrPrompt( + initialSessCfg: SessCfgType, + cmdArgs: ICommandArguments, + connOpts: IOptionsForAddConnProps = {} + ): Promise { + const impLogger = Logger.getImperativeLogger(); + + /* Create copies of our initialSessCfg and connOpts so that + * we can modify them without changing the caller's copy. + */ + const sessCfgToUse = { ...initialSessCfg }; + const connOptsToUse = { ...connOpts }; + + // resolve all values between sessCfg and cmdArgs using option choices + ConnectionPropsForSessCfg.resolveSessCfgProps( + sessCfgToUse, cmdArgs, connOptsToUse + ); + + // This function will provide all the needed properties in one array + let promptForValues: (keyof SessCfgType & string)[] = []; + const doNotPromptForValues: (keyof SessCfgType & string)[] = []; + + /* Add the override properties to the session object. + */ + if (connOpts.propertyOverrides?.length > 0) { + for (const override of connOpts.propertyOverrides) { + const argName = override.argumentName ?? override.propertyName; + // If the override is found on the session or command arguments, start setting things and do not prompt for overridden properties + if ((sessCfgToUse as any)[override.propertyName] != null || cmdArgs[argName] != null) { + // Set the session config to use the command line argument if it exists. + if (cmdArgs[argName] != null) { (sessCfgToUse as any)[override.propertyName] = cmdArgs[argName]; } + for (const prop of override.propertiesOverridden) { + // Make sure we do not prompt for the overridden property. + if (!doNotPromptForValues.includes(prop)) { doNotPromptForValues.push(prop); } + if (prop in sessCfgToUse) { (sessCfgToUse as any)[prop] = undefined; } + } + } + } + } + + // Set default values on propsToPromptFor + if(connOpts.propsToPromptFor?.length > 0) { + connOpts.propsToPromptFor.forEach(obj => { + if(obj.secure == null) obj.secure = true; + if(obj.secure) this.secureSessCfgProps.add(obj.name.toString()); + promptForValues.push(obj.name as keyof ISession); + this.promptTextForValues[obj.name.toString()] = obj.description; + }); + } + // check what properties are needed to be prompted + if (ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.hostname) === false && !doNotPromptForValues.includes("hostname")) { + promptForValues.push("hostname"); + } + + if ((ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.port) === false || sessCfgToUse.port === 0) && + !doNotPromptForValues.includes("port")) { + promptForValues.push("port"); + } + + const isTokenIrrelevant = ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.tokenValue) === false || + connOpts.supportedAuthTypes && !connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_TOKEN); + const isCertIrrelevant = ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.cert) === false || + connOpts.supportedAuthTypes && !connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_CERT_PEM); + if (isTokenIrrelevant && isCertIrrelevant) { + if (ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.user) === false && !doNotPromptForValues.includes("user")) { + promptForValues.push("user"); + } + + if (ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.password) === false && !doNotPromptForValues.includes("password")) { + promptForValues.push("password"); + } + } + + this.loadSecureSessCfgProps(connOptsToUse.parms, promptForValues); + + if (connOptsToUse.getValuesBack == null && connOptsToUse.doPrompting) { + connOptsToUse.getValuesBack = this.getValuesBack(connOptsToUse); + } + + if (connOptsToUse.getValuesBack != null) { + // put all the needed properties in an array and call the external function + const answers = await connOptsToUse.getValuesBack(promptForValues); + + if(connOpts.propsToPromptFor?.length > 0) + { + connOpts.propsToPromptFor.forEach(obj => { + if(obj.isGivenValueValid != null) + { + if(!obj.isGivenValueValid(answers[obj.name])) promptForValues = promptForValues.filter(item => obj.name !== item); + } + }); + } + // validate what values are given back and move it to sessCfgToUse + for (const value of promptForValues) { + if (ConnectionPropsForSessCfg.propHasValue(answers[value])) { + (sessCfgToUse as any)[value] = answers[value]; + } + } + + // + if (connOptsToUse.autoStore !== false && connOptsToUse.parms != null) { + await ConfigAutoStore.storeSessCfgProps(connOptsToUse.parms, sessCfgToUse, promptForValues); + } + } + + AuthOrder.putTopAuthInSession(sessCfgToUse, cmdArgs); + + impLogger.debug("Session config after any prompting for missing values:"); + ConnectionPropsForSessCfg.logSessCfg(sessCfgToUse); + return sessCfgToUse; + } + + // *********************************************************************** + /** + * Resolve the overlapping or mutually exclusive properties that can + * occur. Ensure that the resulting session configuration object contains + * only the applicable properties. The contents of the supplied sessCfg, + * cmdArgs, and connOpts will be modified. + * + * @param sessCfg + * An initial session configuration that contains your desired + * session configuration properties. + * + * @param cmdArgs + * The arguments specified by the user on the command line + * (or in environment, or in profile) + * + * @param connOpts + * Options that alter our actions. See IOptionsForAddConnProps. + * The connOpts parameter need not be supplied. + * The only option values used by this function are: + * connOpts.requestToken + * connOpts.defaultTokenType + * + * @example + * let sessCfg = YouCollectAllProfilePropertiesRelatedToSession(); + * let cmdArgs = YouSetPropertiesRequiredInCmdArgs(); + * ConnectionPropsForSessCfg.resolveSessCfgProps(sessCfg, cmdArgs); + * sessionToUse = new Session(sessCfg); + */ + public static resolveSessCfgProps( + sessCfg: SessCfgType, + cmdArgs: ICommandArguments = { $0: "", _: [] }, + connOpts: IOptionsForAddConnProps = {} + ) { + const impLogger = Logger.getImperativeLogger(); + + // use defaults if caller has not specified these properties. + if (!Object.prototype.hasOwnProperty.call(connOpts, "requestToken")) { + connOpts.requestToken = false; + } + if (!Object.prototype.hasOwnProperty.call(connOpts, "doPrompting")) { + connOpts.doPrompting = true; + } + if (!Object.prototype.hasOwnProperty.call(connOpts, "defaultTokenType")) { + connOpts.defaultTokenType = SessConstants.TOKEN_TYPE_JWT; + } + + /* Override properties from our caller's sessCfg + * with any values from the command line. + */ + if (ConnectionPropsForSessCfg.propHasValue(cmdArgs.host)) { + sessCfg.hostname = cmdArgs.host; + } + if (ConnectionPropsForSessCfg.propHasValue(cmdArgs.port)) { + sessCfg.port = cmdArgs.port; + } + if (ConnectionPropsForSessCfg.propHasValue(cmdArgs.user)) { + sessCfg.user = cmdArgs.user; + } + if (ConnectionPropsForSessCfg.propHasValue(cmdArgs.password)) { + sessCfg.password = cmdArgs.password; + } + + if (connOpts.requestToken) { + // deleting any tokenValue, ensures that basic creds are used to authenticate and get token + delete sessCfg.tokenValue; + } else if (ConnectionPropsForSessCfg.propHasValue(sessCfg.user) === false && + ConnectionPropsForSessCfg.propHasValue(sessCfg.password) === false && + ConnectionPropsForSessCfg.propHasValue(cmdArgs.tokenValue)) { + // set tokenValue if token is in args, and user and password are NOT supplied. + sessCfg.tokenValue = cmdArgs.tokenValue; + } + + // we use a cert when none of user, password, or token are supplied + if (ConnectionPropsForSessCfg.propHasValue(sessCfg.user) === false && + ConnectionPropsForSessCfg.propHasValue(sessCfg.password) === false && + ConnectionPropsForSessCfg.propHasValue(sessCfg.tokenValue) === false && + ConnectionPropsForSessCfg.propHasValue(cmdArgs.certFile)) { + if (ConnectionPropsForSessCfg.propHasValue(cmdArgs.certKeyFile)) { + sessCfg.cert = cmdArgs.certFile; + sessCfg.certKey = cmdArgs.certKeyFile; + } + // else if (ConnectionPropsForSessCfg.propHasValue(cmdArgs.certFilePassphrase)) { + // sessCfg.cert = cmdArgs.certFile; + // sessCfg.passphrase = cmdArgs.certFilePassphrase; + // } + } + + const isTokenUsed = ConnectionPropsForSessCfg.propHasValue(sessCfg.tokenValue) && + (connOpts.supportedAuthTypes == null || connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_TOKEN)); + const isCertUsed = ConnectionPropsForSessCfg.propHasValue(sessCfg.cert) && + (connOpts.supportedAuthTypes == null || connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_CERT_PEM)); + if (isTokenUsed) { + // when tokenValue is set at this point, we are definitely using the token. + impLogger.debug("Using token authentication"); + + // override any token type in sessCfg with cmdArgs value + if (ConnectionPropsForSessCfg.propHasValue(cmdArgs.tokenType)) { + sessCfg.tokenType = cmdArgs.tokenType; + } + + // set the auth type based on token type + if (ConnectionPropsForSessCfg.propHasValue(sessCfg.tokenType)) { + sessCfg.type = SessConstants.AUTH_TYPE_TOKEN; + } else { + // When no tokenType supplied, user wants bearer + sessCfg.type = SessConstants.AUTH_TYPE_BEARER; + } + } else if (isCertUsed) { + // when cert property is set at this point, we will use the certificate + if (ConnectionPropsForSessCfg.propHasValue(sessCfg.certKey)) { + impLogger.debug("Using PEM Certificate authentication"); + sessCfg.type = SessConstants.AUTH_TYPE_CERT_PEM; + } + // else if (ConnectionPropsForSessCfg.propHasValue(sessCfg.passphrase)) { + // impLogger.debug("Using PFX Certificate authentication"); + // sessCfg.type = SessConstants.AUTH_TYPE_CERT_PFX; + // } + } else { + // we are using basic auth + impLogger.debug("Using basic authentication"); + sessCfg.type = SessConstants.AUTH_TYPE_BASIC; + } + ConnectionPropsForSessCfg.setTypeForTokenRequest(sessCfg, connOpts, cmdArgs.tokenType); + ConnectionPropsForSessCfg.logSessCfg(sessCfg); + } + + // *********************************************************************** + /** + * Confirm whether the given session has a credentials. + * + * @param sessToTest + * the session to be confirmed. + * + * @returns true is the session has credentials. false otherwise. + */ + public static sessHasCreds(sessToTest: ISession) { + if (sessToTest == null) { + return false; + } + const hasToken = sessToTest.tokenType != null && sessToTest.tokenValue != null; + const hasCert = sessToTest.certKey != null && sessToTest.cert; + const hasBasicAuth = sessToTest.base64EncodedAuth != null; + const hasCreds = sessToTest.user != null && sessToTest.password; + return hasToken || hasCert || hasBasicAuth || hasCreds; + } + + /** + * List of properties on `sessCfg` object that should be kept secret and + * may not appear in Imperative log files. + * + * NOTE(Kelosky): redundant from LoggerUtils.SECURE_PROMPT_OPTIONS - leaving + * for future date to consolidate + */ + private static secureSessCfgProps: Set = new Set(["user", "password", "tokenValue", "passphrase"]); + + /** + * List of prompt messages that is used when the CLI prompts for session + * config values. + */ + private static readonly promptTextForValues: { [key: string]: string } = { + hostname: "Enter the host name of", + port: "Enter the port number of", + user: "Enter the user name for", + password: "Enter the password for" + }; + + /** + * Prompts the user to input session config values in a CLI environment. + * This is the default implementation of the `getValuesBack` callback when + * `connOpts.doPrompting` is true. + * @param connOpts Options for adding connection properties + * @returns Name-value pairs of connection properties + */ + private static getValuesBack(connOpts: IOptionsForAddConnProps): + (properties: string[]) => Promise<{ [key: string]: any }> { + return async (promptForValues: string[]) => { + /* The check for console.log in the following 'if' statement is only needed for tests + * which do not create a mock for the connOpts.parms.response.console.log property. + * In the real world, that property always exists for this CLI-only path of logic. + */ + if (promptForValues.length > 0 && connOpts.parms?.response.console.log) { + // We need to prompt for some values. Determine why we need to prompt. + let reasonForPrompts: string = ""; + if (ImperativeConfig.instance.config?.exists) { + reasonForPrompts += "Some required connection properties have not been specified " + + "in your Zowe client configuration. "; + } else if (ConfigUtils.onlyV1ProfilesExist) { + reasonForPrompts += "Only V1 profiles exist. V1 profiles are no longer supported. " + + "You should convert your V1 profiles to a newer Zowe client configuration. "; + } else { + reasonForPrompts += "No Zowe client configuration exists. "; + } + + reasonForPrompts += "Therefore, you will be asked for the connection properties " + + "that are required to complete your command.\n"; + connOpts.parms.response.console.log(TextUtils.wordWrap( + TextUtils.chalk.yellowBright(reasonForPrompts)) + ); + } + + const answers: { [key: string]: any } = {}; + const profileSchema = this.loadSchemaForSessCfgProps(connOpts.parms, promptForValues); + const serviceDescription = connOpts.serviceDescription || "your service"; + + for (const value of promptForValues) { + let answer; + while (answer === undefined) { + const hideText = profileSchema[value]?.secure || this.secureSessCfgProps.has(value); + const valuePrompt = this.promptTextForValues[value] ?? `Enter your ${value} for`; + let promptText = `${valuePrompt} ${serviceDescription}`; + if (hideText) { + promptText += " (will be hidden)"; + } + answer = await this.clientPrompt(`${promptText}: `, { hideText, parms: connOpts.parms }); + if (answer === null) { + throw new ImperativeError({ msg: `Timed out waiting for ${value}.` }); + } + } + if (profileSchema[value]?.type === "number") { + answer = Number(answer); + if (isNaN(answer)) { + throw new ImperativeError({ msg: `Specified ${value} was not a number.` }); + } + } + answers[value] = answer; + } + + return answers; + }; + } + + /** + * Handle prompting for clients. If in a CLI environment, use the IHandlerParameters.response + * object prompt method. + * @private + * @static + * @param {string} promptText + * @param {IHandlePromptOptions} opts + * @returns {Promise} + * @memberof ConnectionPropsForSessCfg + */ + private static async clientPrompt(promptText: string, opts: IHandlePromptOptions): Promise { + if (opts.parms) { + return opts.parms.response.console.prompt(promptText, opts); + } else { + return CliUtils.readPrompt(promptText, opts); + } + } + + // *********************************************************************** + /** + * Determine if we want to request a token. + * Set the session's type and tokenType accordingly. + * + * @param sessCfg + * The session configuration to be updated. + * + * @param options + * Options that alter our actions. See IOptionsForAddConnProps. + * + * @param tokenType + * The type of token that we expect to receive. + */ + private static setTypeForTokenRequest( + sessCfg: SessCfgType, + options: IOptionsForAddConnProps, + tokenType: SessConstants.TOKEN_TYPE_CHOICES + ) { + const impLogger = Logger.getImperativeLogger(); + if (options.requestToken) { + impLogger.debug("Requesting a token"); + if (sessCfg.type === SessConstants.AUTH_TYPE_BASIC) { + // Set our type to token to get a token from user and pass + sessCfg.type = SessConstants.AUTH_TYPE_TOKEN; + } + sessCfg.tokenType = tokenType || sessCfg.tokenType || options.defaultTokenType; + } + } + + // *********************************************************************** + /** + * Log the session configuration that resulted from the addition of + * credentials. Hide the password. + * + * @param sessCfg + * The session configuration to be logged. + */ + private static logSessCfg(sessCfg: any) { + const impLogger = Logger.getImperativeLogger(); + + // create copy of sessCfg and obscure secure fields for displaying in the log + const sanitizedSessCfg = JSON.parse(JSON.stringify(sessCfg)); + for (const secureProp of ConnectionPropsForSessCfg.secureSessCfgProps) { + if (sanitizedSessCfg[secureProp] != null) { + sanitizedSessCfg[secureProp] = `${secureProp}_is_hidden`; + } + } + impLogger.debug("Creating a session config with these properties:\n" + + JSON.stringify(sanitizedSessCfg, null, 2) + ); + } + + // *********************************************************************** + /** + * Confirm whether the specified property has a value. + * + * @param propToTest + * the property key to be confirmed. + * + * @returns true is the property exists and has a value. false otherwise. + */ + private static propHasValue(propToTest: any) { + return propToTest != null && propToTest !== ""; + } + + /** + * Load base profile property schema for connection properties. + * @param params CLI handler parameters object + * @param promptForValues List of ISessCfg properties to prompt for + * @returns Key-value pairs of ISessCfg property name and profile property schema + */ + private static loadSchemaForSessCfgProps(params: IHandlerParameters | undefined, promptForValues: string[]): { [key: string]: IProfileProperty } { + if (params == null || ImperativeConfig.instance.loadedConfig?.baseProfile == null) { + return {}; + } + + const schemas: { [key: string]: IProfileProperty } = {}; + for (const propName of promptForValues) { + const profilePropName = propName === "hostname" ? "host" : propName; + schemas[propName] = ImperativeConfig.instance.loadedConfig.baseProfile.schema.properties[profilePropName]; + } + return schemas; + } + + /** + * Load list of secure property names defined in team config. + * @param params CLI handler parameters object + * @param promptForValues List of ISessCfg properties to prompt for + */ + private static loadSecureSessCfgProps(params: IHandlerParameters | undefined, promptForValues: string[]): void { + if (params == null || !ImperativeConfig.instance.config?.exists) { + return; + } + + // Find profile that includes all the properties being prompted for + const profileProps = promptForValues.map(propName => propName === "hostname" ? "host" : propName); + const profileData = ConfigAutoStore.findActiveProfile(params, profileProps); + if (profileData == null) { + return; + } + + // Load secure property names that are defined for active profiles + const config = ImperativeConfig.instance.config; + const baseProfileName = ConfigUtils.getActiveProfileName("base", params.arguments); + for (const secureProp of [...config.api.secure.securePropsForProfile(profileData[1]), + ...config.api.secure.securePropsForProfile(baseProfileName)]) { + this.secureSessCfgProps.add(secureProp === "host" ? "hostname" : secureProp); + } + } +} \ No newline at end of file diff --git a/prototypes/packages/imperative/src/rest/src/session/Readme.md b/prototypes/packages/imperative/src/rest/src/session/Readme.md new file mode 100644 index 0000000000..5a1554004d --- /dev/null +++ b/prototypes/packages/imperative/src/rest/src/session/Readme.md @@ -0,0 +1,7 @@ +Files used to create a prototype of AuthOrder are: + +prototypes\packages\imperative\src\rest\src\session\AuthOrder.ts + +prototypes\packages\imperative\src\rest\src\session\ConnectionPropsForSessCfg.ts + +prototypes\packages\cli\src\zosfiles\list\ds\DataSet.handler.ts From 91d425e513b01ae43597a6571bdbd1b8871e9f64 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Fri, 13 Dec 2024 12:16:01 -0500 Subject: [PATCH 39/61] No env var, cmd-line option, or schema. AuthOrder reserved word. Signed-off-by: Gene Johnston --- docs/Design_for_selecting_auth_type.md | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/Design_for_selecting_auth_type.md b/docs/Design_for_selecting_auth_type.md index 88c7ed944b..9466b16a2d 100644 --- a/docs/Design_for_selecting_auth_type.md +++ b/docs/Design_for_selecting_auth_type.md @@ -32,10 +32,22 @@ In this section we identify the key features that a solution would have to provi - For example, assume that a user has specified that a certificate should be used before a token. Assume that a certificate is supplied in a config file and a token is supplied on the command line. - - The certificate should be used because the user configured that certificates should be used before tokens. + - The certificate should be used because the user-configured authentication order specifies that certificates should be used before tokens. - The token should not be used just because it was supplied on the command line. +- Zowe should ignore any authentication order property that is specified in a environment variable (unlike most other connection properties). + + - A single environment variable property would override **every** authentication order property specified in **every** profile within the user's zowe.config.json file. The most likely customer use of this property will be to specify a different authentication order for different profiles. A single environment variable would likely defeat the primary purpose of enabling a user to specify a different authentication order for different profiles. + +- The authentication order **could** be specified on the command line. However, in the initial implementation of this feature, Zowe CLI will **NOT** implement a command line option for the authentication order. + + - Conceptually, specifying an authentication order as a command line option is a reasonable idea. However, implementing that behavior could involve modifications to dozens of CLI command handlers, which could increase our implementation effort and time-to-market significantly. + + - It is not clear whether a command line option for authentication order will be particularly valuable to customers. The authentication order would typically be static for a given profile. It is unlikely to change from one CLI command to another. + + - Therefore, we will **NOT** implement a command-line option for authentication order until customer demand makes such work a priority. + - The authentication order only identifies the order in which Zowe chooses the **one** authentication method that will be used. If that first authentication method fails, Zowe will not make a second attempt to authenticate with any of the later authentication methods. - Once an authentication is selected, our logic should ensure that only that one type of authentication is placed into a session object. Thus, logic in down-stream Zowe code will not alter the order of authentication selection, simply by testing for the authentications from the session in a different order than the order that the user specified. @@ -48,7 +60,7 @@ In this section we identify the key features that a solution would have to provi - A customer should not have to specify every possible authentication in their ordered list of authentications. If a site only uses password and tokens, the customer should be able to specify only those two authentications in their list. -- A customer-specified list of authentications must contain at least one of our supported authentications. +- If a customer-specified list of authentications contains none of our supported authentications, a default order will be used. - The `--show-input-only` option should show the order of authentication as part of its displayed connection properties. @@ -84,7 +96,7 @@ A new profile property named **authOrder** should be created to enable users to - Any service profile. - - Any profile specific to a plugin (or VSCode extension) that supports a REST connection. For example an **endevor** profile could contain an **authOrder** property, but an **endevor-location** profile would not. + - Any profile specific to a plugin (or VSCode extension) that supports a REST connction. For example an **endevor** profile could contain an **authOrder** property, but an **endevor-location** profile would not. - Our existing inheritance of connection properties should also apply to the inheritance of the authOrder property. @@ -94,11 +106,9 @@ A new profile property named **authOrder** should be created to enable users to - Such a new item within the properties object will not currently be included in the zowe.schema.json file. An IntelliSense-like editor will not display **authOrder** as an option when a user starts to add a new property in a profile. - - We do not want to require plugins/extensions to add **authOrder** to their profiles. Requesting new work from plugins/extensions in the middle of a release's lifecycle can be a burden for those contributors. + - We do not want to require plugins/extensions to add **authOrder** to their profiles. Asking extenders to add AuthOrder to their set of options (and thus the schema) in the middle of a release's lifecycle can be a burden for those contributors. - - When the CLI is installed, the schema is not updated, so the CLI cannot currently take on that burden. It is possible that a CLI post-install step could be performed to update the schema. This is not considered to be a trivial task. - - - It should be noted if **authOrder** is absent from the schema, users will lose a nice convenience, but the user's config will not be broken in any functional way. + - As a result, we feel that losing IntelliSense is an acceptable compromise to avoid adding work to every extender. Users will lose a nice convenience, but the user's config will not be limited in any way at runtime. To represent a series of values, the **authOrder** property should be an array. The following example shows how a user could specify their desired authOrder. @@ -143,6 +153,8 @@ That addition would enable customers to also specify the authentication order of - We must describe the default order of authentication, when no authOrder property is supplied. +- We must document that the new authOrder property name is a Zowe reserved word that should **NOT** be used by any extender. + - We must notify extenders to guide their customers to supply an appropriate authOrder property if their extension needs a non-default order. ## A new class must be created to support authOrder From 60058ae7e15d16edb7a851890b52335684406157 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Fri, 13 Dec 2024 12:24:31 -0500 Subject: [PATCH 40/61] Remove AuthOrder.ts from our real packages directory Signed-off-by: Gene Johnston --- .../src/rest/src/session/AuthOrder.ts | 326 ------------------ 1 file changed, 326 deletions(-) delete mode 100644 packages/imperative/src/rest/src/session/AuthOrder.ts diff --git a/packages/imperative/src/rest/src/session/AuthOrder.ts b/packages/imperative/src/rest/src/session/AuthOrder.ts deleted file mode 100644 index 3052c86e72..0000000000 --- a/packages/imperative/src/rest/src/session/AuthOrder.ts +++ /dev/null @@ -1,326 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandArguments } from "../../../cmd"; -import { ImperativeError } from "../../../error"; -import { ISession } from "./doc/ISession"; -import { Logger } from "../../../logger"; -import * as SessConstants from "./SessConstants"; - -/** - * @internal - Cannot be used outside of the imperative package - * - * The purpose of this class is to detect an authentication order property - * supplied by a user in a profile, command line, or environment variable. - * That authOrder is then used to place the correct set of credentials into - * a session for authentication. - */ -export class AuthOrder { - - /** - * When a user does not supply an auth order, Zowe clients will use a - * hard-coded default order. This property records whether AUTH_TYPE_BASIC - * or AUTH_TYPE_TOKEN is the top auth choice in the order. - */ - private static m_topDefaultAuth: string = SessConstants.AUTH_TYPE_BASIC; - - /** - * This array of authentication types specifies the order of preferred - * authentication. It contains the user-specified order, or a default order - * if the user does not specify an order. m_authOrder[0] is the highest - * preferred authentication. - */ - private static m_authOrder: SessConstants.AUTH_TYPE_CHOICES[] = null; - - // *********************************************************************** - /** - * Set the top auth type when a default authOrder is used. Previously, - * two different hard-coded orders were present in the Zowe clients. - * Both hard-coded orders are now provided by this class. Zowe code, - * that still sets a specific order for backward compatibility, now - * calls this function to ensure that that the original behavior remains - * the same and avoids a breaking change when a user has not specified - * an authOrder property. - * - * @param topDefaultAuth - Input. - * The top authentication type that will be used when forming a - * default authOrder. - */ - public static setTopDefaultAuth( - topDefaultAuth: typeof SessConstants.AUTH_TYPE_BASIC | typeof SessConstants.AUTH_TYPE_TOKEN - ): void { - AuthOrder.m_topDefaultAuth = topDefaultAuth; - } - - // *********************************************************************** - /** - * Cache the authOrder property from the supplied cmdArgs. If no authOrder exists - * in cmdArgs, a default authOrder is created and cached. - * - * @param cmdArgs - Input. - * The set of arguments that the calling function is using. - */ - private static cacheAuthOrder(cmdArgs: ICommandArguments): void { - // have we already cached the authOrder? - if (AuthOrder.m_authOrder !== null) { - // start over with an empty order. - AuthOrder.m_authOrder = null; - } - - if (cmdArgs.authOrder) { - // validate each user-supplied type of authentication - for (const nextUserAuth of cmdArgs.authOrder) { - switch (nextUserAuth) { - case SessConstants.AUTH_TYPE_BASIC: - case SessConstants.AUTH_TYPE_TOKEN: - case SessConstants.AUTH_TYPE_BEARER: - case SessConstants.AUTH_TYPE_CERT_PEM: - case SessConstants.AUTH_TYPE_NONE: - if (AuthOrder.m_authOrder === null) { - AuthOrder.m_authOrder = []; - } - AuthOrder.m_authOrder.push(nextUserAuth); - break; - default: - Logger.getImperativeLogger().error( - `The authentication = '${nextUserAuth}' is not valid and will be ignored.` - ); - /* todo: Remove diagnostic print statements - console.log("____ cacheAuthOrder: nextUserAuth = '" + nextUserAuth + "' is not valid and will be ignored."); - // end Remove todo: */ - } - } - } - - // the user supplied an authOrder - if (AuthOrder.m_authOrder !== null) { - /* todo: Remove diagnostic print statements - console.log("____ cacheAuthOrder: cached authOrder = " + AuthOrder.m_authOrder); - // end Remove todo: */ - return; - } - - // No authOrder was supplied by the user. Create a default order. - AuthOrder.m_authOrder = []; - if (AuthOrder.m_topDefaultAuth === SessConstants.AUTH_TYPE_BASIC) { - // we want user & password auth as the top choice - AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_BASIC); - AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_TOKEN); - } else { - // we want token auth as the top choice - AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_TOKEN); - AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_BASIC); - } - // add remaining auth types. We do not include 'none' in our defaults. - AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_BEARER); - AuthOrder.m_authOrder.push(SessConstants.AUTH_TYPE_CERT_PEM); - /* todo: Remove diagnostic print statements - console.log("____ cacheAuthOrder: cached authOrder = " + AuthOrder.m_authOrder); - // end Remove todo: */ - } - - // *********************************************************************** - /** - * Find the highest auth type (according to the authOrder) which exists - * in either the supplied session config or command line arguments. - * Then place the credentials associated with that auth type into the - * supplied session config. Credentials for all other auth types are - * removed from the session config. - * - * @param sessCfg - Modified. - * Authentication properties are added to and removed from this - * session configuration, which can already have properties in - * this object when passed to this function. - * - * @param cmdArgs - Input. - * The set of arguments with which the calling function is operating. - * For CLI, the cmdArgs come from the command line, profile, or - * environment. Other apps can place relevant arguments into this - * object to be processed by this function. - */ - public static putTopAuthInSession( - sessCfg: SessCfgType, - cmdArgs: ICommandArguments - ): void { - let sessTypeToUse: SessConstants.AUTH_TYPE_CHOICES = null; - - // cache the correct authOrder to use - AuthOrder.cacheAuthOrder(cmdArgs); - - /* todo: Remove diagnostic print statements - sessCfg.tokenType = "apimlAuthenticationToken"; - sessCfg.tokenValue = "SomeTokenValue"; - sessCfg.cert = "./certFile.txt"; - sessCfg.certKey = "./certKeyFile.txt"; - sessCfg.authTypeOrder = []; - sessCfg.authTypeOrder.push("bogusAuthType1"); - sessCfg.authTypeOrder.push("bogusAuthType2"); - sessCfg.authTypeOrder.push("bogusAuthType3"); - sessCfg.authTypeOrder.push("bogusAuthType4"); - console.log("____ putTopAuthInSession:\ncmdArgs = " + JSON.stringify(cmdArgs, null, 2)); - console.log("____ putTopAuthInSession:\nsessCfg before processing = " + JSON.stringify(sessCfg, null, 2)); - // end Remove todo: */ - - // Detect the first auth type (from our auth order) provided in the session config or in command args. - // Ensure that the auth properties are placed in the session config. - // Record the detected auth type for use as the session type. - let errMsg: string; - for (const nextAuth of AuthOrder.m_authOrder) { - switch (nextAuth) { - case SessConstants.AUTH_TYPE_BASIC: - // todo: do we have to check for sessCfg.base64EncodedAuth ? - if (cmdArgs.user?.length > 0) { - sessCfg.user = cmdArgs.user; - } - if (cmdArgs.password?.length > 0) { - sessCfg.password = cmdArgs.password; - } - if (sessCfg.user?.length > 0 && sessCfg.password?.length > 0) { - // TODO: Confirm in ConnectionPropsForSessCfg that requestToken will work ok with sessTypeToUse - sessTypeToUse = SessConstants.AUTH_TYPE_BASIC; - } - break; - case SessConstants.AUTH_TYPE_TOKEN: - if (cmdArgs.tokenType?.length > 0) { - sessCfg.tokenType = cmdArgs.tokenType; - } - if (cmdArgs.tokenValue?.length > 0) { - sessCfg.tokenValue = cmdArgs.tokenValue; - } - if (sessCfg.tokenType?.length > 0 && sessCfg.tokenValue?.length > 0) { - sessTypeToUse = SessConstants.AUTH_TYPE_TOKEN; - } - break; - case SessConstants.AUTH_TYPE_BEARER: - if (cmdArgs.tokenType?.length > 0) { - sessCfg.tokenType = cmdArgs.tokenType; - } - if (cmdArgs.tokenValue?.length > 0) { - sessCfg.tokenValue = cmdArgs.tokenValue; - } - // a tokenValue with no tokenType implies a bearer token - if (!(sessCfg.tokenType?.length > 0) && sessCfg.tokenValue?.length > 0) { - sessTypeToUse = SessConstants.AUTH_TYPE_BEARER; - } - break; - case SessConstants.AUTH_TYPE_CERT_PEM: - if (cmdArgs.certFile?.length > 0) { - sessCfg.cert = cmdArgs.certFile; - } - if (cmdArgs.certKeyFile?.length > 0) { - sessCfg.certKey = cmdArgs.certKeyFile; - } - if (sessCfg.cert?.length > 0 && sessCfg.certKey?.length > 0) { - sessTypeToUse = SessConstants.AUTH_TYPE_CERT_PEM; - } - break; - case SessConstants.AUTH_TYPE_NONE: - sessTypeToUse = SessConstants.AUTH_TYPE_NONE; - break; - default: - // authOrder was validated. A wrong value now is our programming error. - errMsg = `authOrder contains an invalid authentication = ${nextAuth}.`; - Logger.getImperativeLogger().error(errMsg); - throw new ImperativeError({ msg: errMsg }); - } - if (sessTypeToUse !== null) { - // stop looking for auth types after we find the first one - break; - } - } - - // When no creds are in the session and AUTH_TYPE_NONE is not in the user's authOrder, - // remove the session type from the session. Otherwise set the type that we found. - if (sessTypeToUse === null) { - delete sessCfg.type; - } else { - sessCfg.type = sessTypeToUse; - } - - // remove all extra auth creds from the session - AuthOrder.removeExtraCredsFromSess(sessCfg); - - // copy our authOrder into the session object - sessCfg.authTypeOrder = [...AuthOrder.m_authOrder]; - - // todo: Should we throw error if no creds are in the session, or let other functions throw the error? - - /* todo: Remove diagnostic print statements - console.log("____ putTopAuthInSession:\nsessCfg after processing = " + JSON.stringify(sessCfg, null, 2)); - // end Remove todo: */ - } - - // *********************************************************************** - /** - * Remove all credential properties from the supplied session except for the - * creds related to the session type specified within the sessCfg argument. - * - * @param sessCfg - Modified. - * Authentication credentials are removed from this session configuration. - */ - private static removeExtraCredsFromSess( - sessCfg: SessCfgType - ): void { - if (AuthOrder.cacheAuthOrder == null) { - const errMsg = "AuthOrder.cacheAuthOrder must be called before AuthOrder.removeExtraCredsFromSess"; - Logger.getImperativeLogger().error(errMsg); - throw new ImperativeError({ msg: errMsg }); - } - if (!sessCfg?.type) { - const errMsg = "Session type must exist in the supplied session."; - Logger.getImperativeLogger().error(errMsg); - throw new ImperativeError({ msg: errMsg }); - } - - // initially set all creds to be removed from the session. Later we delete the desired creds from this set - const credsToRemove = new Set(["user", "password", "base64EncodedAuth", "tokenType", "tokenValue", "cert", "certKey"]); - - // Delete the selected creds from the set of creds that will be removed from our session config. - let errMsg: string; - switch (sessCfg.type) { - case SessConstants.AUTH_TYPE_BASIC: - credsToRemove.delete("user"); - credsToRemove.delete("password"); - credsToRemove.delete("base64EncodedAuth"); - break; - case SessConstants.AUTH_TYPE_TOKEN: - credsToRemove.delete("tokenType"); - credsToRemove.delete("tokenValue"); - break; - case SessConstants.AUTH_TYPE_BEARER: - credsToRemove.delete("tokenValue"); - break; - case SessConstants.AUTH_TYPE_CERT_PEM: - credsToRemove.delete("cert"); - credsToRemove.delete("certKey"); - break; - case SessConstants.AUTH_TYPE_NONE: - break; - default: - // authOrder was validated. A wrong value now is our programming error. - errMsg = `Session an invalid type = ${sessCfg.type}.`; - Logger.getImperativeLogger().error(errMsg); - throw new ImperativeError({ msg: errMsg }); - } - - // remove all auth creds from the session, except the creds for the auth type that we chose to keep - const credIter = credsToRemove.values(); - let nextCredToRemove = credIter.next(); - while (!nextCredToRemove.done) { - /* todo: Remove diagnostic print statements - console.log("____ removeExtraCredsFromSess: deleting = 'sessCfg." + nextCredToRemove.value + "' from the session."); - // end Remove todo: */ - - delete (sessCfg as any)[nextCredToRemove.value]; - nextCredToRemove = credIter.next(); - } - } -} \ No newline at end of file From 4eb68d89932cc01d90201cabac72e6606d18c4cd Mon Sep 17 00:00:00 2001 From: Rudy Flores <68666202+rudyflores@users.noreply.github.com> Date: Fri, 13 Dec 2024 12:53:38 -0500 Subject: [PATCH 41/61] Add CHANGELOG.md Signed-off-by: Rudy Flores <68666202+rudyflores@users.noreply.github.com> --- packages/imperative/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index ded21b7c84..52915b7f41 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to the Imperative package will be documented in this file. - BugFix: Modified 8.8.2 bugfix to correct web help alias. [#2361](https://github.com/zowe/zowe-cli/pull/2361) - BugFix: Resolved issue where special characters could be corrupted when downloading a large file. [#2366](https://github.com/zowe/zowe-cli/pull/2366) +- BugFix: Modified location of Proxy-Authorization header to be located in the agent instead of the request. ## `8.8.2` From cd5b2cf6437c978dd3738b1ca284c5b5217f38df Mon Sep 17 00:00:00 2001 From: Rudy Flores <68666202+rudyflores@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:25:26 -0500 Subject: [PATCH 42/61] Fix broken unit tests Signed-off-by: Rudy Flores <68666202+rudyflores@users.noreply.github.com> --- .../client/AbstractRestClient.unit.test.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/packages/imperative/src/rest/__tests__/client/AbstractRestClient.unit.test.ts b/packages/imperative/src/rest/__tests__/client/AbstractRestClient.unit.test.ts index fcd7669552..98005ccff5 100644 --- a/packages/imperative/src/rest/__tests__/client/AbstractRestClient.unit.test.ts +++ b/packages/imperative/src/rest/__tests__/client/AbstractRestClient.unit.test.ts @@ -1502,22 +1502,6 @@ describe("AbstractRestClient tests", () => { const result = privateRestClient.buildOptions(resource, request, reqHeaders); expect(Object.keys(result)).toContain('agent'); }); - - it('Should use session proxy options over env vars for proxy agent', () => { - restSession.ISession.proxy = { proxy_authorization: 'proxy_auth_string'}; - const resource = '/resource'; - const request = ''; - const reqHeaders: any[] = []; - const url = new URL('https://www.zowe.com'); - const proxyAgent = new HttpsProxyAgent(url, { rejectUnauthorized: true }); - getSystemProxyUrlSpy.mockReturnValue(url); - getProxyAgentSpy.mockReturnValue(proxyAgent); - setCertPemAuthSpy.mockReturnValue(true); - const headerSpy = jest.spyOn(privateRestClient, "appendHeaders"); - const result = privateRestClient.buildOptions(resource, request, reqHeaders); - expect(Object.keys(result)).toContain('agent'); - expect(headerSpy).toHaveBeenCalledWith([{'Proxy-Authorization': restSession.ISession.proxy.proxy_authorization}]); - }); }); }); }); From ac0338e558b0c169c11bd9b969e64557bf136ac8 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Mon, 16 Dec 2024 09:09:06 -0500 Subject: [PATCH 43/61] added buffer and stream inspect Signed-off-by: jace-roell --- .../methods/upload/Upload.unit.test.ts | 32 +++++++++++++++---- .../zosfiles/src/methods/upload/Upload.ts | 15 +++++---- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts index 69420591e3..c0f92eb905 100644 --- a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts +++ b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts @@ -22,7 +22,7 @@ import { IUploadOptions } from "../../../../src/methods/upload/doc/IUploadOption import { Upload } from "../../../../src/methods/upload/Upload"; import { List } from "../../../../src/methods/list/List"; import { Utilities } from "../../../../src/methods/utilities/Utilities"; - +import { inspect } from "util"; import { ZosFilesUtils } from "../../../../src/utils/ZosFilesUtils"; import { stripNewLines } from "../../../../../../__tests__/__src__/TestUtils"; import { Create } from "../../../../src/methods/create"; @@ -379,7 +379,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error).toBe(testError); }); - it("should return with proper response when upload buffer to a data set", async () => { + it("should return with proper response when upload buffer to a data set - buffer less than 10 chars", async () => { const buffer: Buffer = Buffer.from("testing"); const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsName); const reqHeaders = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.ACCEPT_ENCODING]; @@ -392,7 +392,27 @@ describe("z/OS Files - Upload", () => { expect(error).toBeUndefined(); expect(response).toBeDefined(); - expect(response.apiResponse).toMatchObject({"from": "Buffer<>", "success": true, "to": dsName}); + expect(response.apiResponse).toMatchObject({"from": "", "success": true, "to": dsName}); + + expect(zosmfPutFullSpy).toHaveBeenCalledTimes(1); + expect(zosmfPutFullSpy).toHaveBeenCalledWith(dummySession, {resource: endpoint, + reqHeaders, + writeData: buffer}); + }); + it("should return with proper response when upload buffer to a data set - buffer more than 10 chars", async () => { + const buffer: Buffer = Buffer.from("bufferLargerThan10Chars"); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsName); + const reqHeaders = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.ACCEPT_ENCODING]; + + try { + response = await Upload.bufferToDataSet(dummySession, buffer, dsName); + } catch (err) { + error = err; + } + + expect(error).toBeUndefined(); + expect(response).toBeDefined(); + expect(response.apiResponse).toMatchObject({"from": "", "success": true, "to": dsName}); expect(zosmfPutFullSpy).toHaveBeenCalledTimes(1); expect(zosmfPutFullSpy).toHaveBeenCalledWith(dummySession, {resource: endpoint, @@ -749,7 +769,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeUndefined(); expect(response).toBeDefined(); - expect(response.apiResponse).toMatchObject({"from": "Stream<>", "success": true, "to": dsName}); + expect(response.apiResponse).toMatchObject({"from": "[Readable]", "success": true, "to": dsName}); expect(zosmfPutFullSpy).toHaveBeenCalledTimes(1); expect(zosmfPutFullSpy).toHaveBeenCalledWith(dummySession, {resource: endpoint, @@ -1757,7 +1777,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeUndefined(); expect(USSresponse).toBeDefined(); - expect(USSresponse.apiResponse).toMatchObject({"from": "Buffer<>", "success": true, "to": dsName}); + expect(USSresponse.apiResponse).toMatchObject({"from": "", "success": true, "to": dsName}); const normalizedData = ZosFilesUtils.normalizeNewline(data); expect(data.length).not.toBe(normalizedData.length); @@ -1833,7 +1853,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeUndefined(); expect(USSresponse).toBeDefined(); - expect(USSresponse.apiResponse).toMatchObject({"from": "Stream<>", "success": true, "to": dsName}); + expect(USSresponse.apiResponse).toMatchObject({"from": "[Readable]", "success": true, "to": dsName}); expect(USSresponse.success).toBeTruthy(); expect(zosmfExpectFullSpy).toHaveBeenCalledTimes(1); diff --git a/packages/zosfiles/src/methods/upload/Upload.ts b/packages/zosfiles/src/methods/upload/Upload.ts index 4280d80e41..9301c81bfc 100644 --- a/packages/zosfiles/src/methods/upload/Upload.ts +++ b/packages/zosfiles/src/methods/upload/Upload.ts @@ -30,7 +30,7 @@ import { Utilities, Tag } from "../utilities"; import { Readable } from "stream"; import { CLIENT_PROPERTY } from "../../doc/types/ZosmfRestClientProperties"; import { TransferMode } from "../../utils/ZosFilesAttributes"; - +import { inspect } from "util"; export class Upload { @@ -183,10 +183,11 @@ export class Upload { } const uploadRequest: IRestClientResponse = await ZosmfRestClient.putExpectFullResponse(session, requestOptions); + const maxBufferPreviewSize = 10; // By default, apiResponse is empty when uploading const apiResponse: any = { success: true, - from: "Buffer<>", + from: fileBuffer.length > maxBufferPreviewSize ? inspect(fileBuffer.subarray(0, maxBufferPreviewSize)).slice(0, -1) + "...>" : inspect(fileBuffer), to: dataSetName }; @@ -248,7 +249,7 @@ export class Upload { // By default, apiResponse is empty when uploading const apiResponse: any = { success: true, - from: "Stream<>", + from: inspect(fileStream, { showHidden: false, depth: -1}), to: dataSetName }; @@ -488,11 +489,11 @@ export class Upload { } const uploadRequest: IRestClientResponse = await ZosmfRestClient.putExpectFullResponse(session, requestOptions); + const maxBufferPreviewSize = 10; // By default, apiResponse is empty when uploading - const apiResponse: any = - { + const apiResponse: any = { success: true, - from: "Buffer<>", + from: fileBuffer.length > maxBufferPreviewSize ? inspect(fileBuffer.subarray(0, maxBufferPreviewSize)).slice(0, -1) + "...>" : inspect(fileBuffer), to: origUssname }; @@ -556,7 +557,7 @@ export class Upload { // By default, apiResponse is empty when uploading const apiResponse: any = { success: true, - from: "Stream<>", + from: inspect(uploadStream, { showHidden: false, depth: -1}), to: origUssname }; From c3edfd6951ae2d30dbfce27c45a8c68b3e538b06 Mon Sep 17 00:00:00 2001 From: anaxceron Date: Mon, 16 Dec 2024 10:33:24 -0500 Subject: [PATCH 44/61] addressing Fernando feedback Signed-off-by: anaxceron --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ca07245ec6..b8a9c0c926 100644 --- a/README.md +++ b/README.md @@ -54,11 +54,11 @@ Versioning conventions for Zowe CLI and Plug-ins| [Versioning guidelines](./docs ## Building Zowe CLI from source -Zowe CLI requires NPM version 8 and Cargo version 1.72.0 (or newer) to build from source. +Zowe CLI requires the NPM version bundled with the active LTS versions of NodeJS and Cargo version 1.72.0 (or newer) to build from source. Check your NPM version with `npm --version` and if it's older than 8.x, update with `npm install -g npm`. -Check your vCargo version with `cargo --version`. Cargo can be installed using [rustup](https://rustup.rs/). To update Cargo, run the `rustup update` command. +Check your Cargo version with `cargo --version`. Cargo can be installed using [rustup](https://rustup.rs/). To update Cargo, run the `rustup update` command. For developers using Linux, the following packages are required to build Zowe CLI from source: @@ -139,9 +139,11 @@ For detailed information about creating profiles, or integrating with Zowe API M If you try to use Zowe CLI functionality and you get an error message that Zowe CLI failed to load any profiles, try issuing the following commands: +- `zowe config report-env` to generate a report on the status of the key areas in your working environment. Address any problems indicated in the report. - `zowe config edit` to open your `~/.zowe/zowe.config.json` configuration file in your system's default text editor. Fix any properties with incorrect values. - `zowe config secure` to have Zowe CLI prompt for your secure configuration properties in case your secure values are incorrect in your configuration. -- `zowe config report-env` to generate a report on the status of the key areas in your working environment. Address any problems indicated in the report. + +**Note:** For these commands, use the `--global-config` option to update your global configuration or `--user-config` for your user configuration. ## Zowe Node Client SDK @@ -163,7 +165,7 @@ Alternatively, import Zowe CLI into your project to call the Node APIs. However, ### Example API usage -For example usage syntax, see the ReadMe for each API package in this repository: +For example usage syntax, see the README for each API package in this repository: - [Provisioning](https://github.com/zowe/zowe-cli/tree/master/packages/provisioning): Provision middleware and resources such as IBM CICS, IBM Db2, IBM MQ, and more. - [z/OS Console](https://github.com/zowe/zowe-cli/tree/master/packages/zosconsole): Perform z/OS console operations. @@ -221,16 +223,16 @@ npm run test:system ### What is the difference between Zowe V2 and V3? - - V3 deprecates support for Zowe V1 profiles. - - - To updgrade from an older Zowe release, see [Migrating from Zowe Vx to Zowe V3](https://docs.zowe.org/stable/whats-new/zowe-v3-migratio3). - - - V2 uses **team profiles** and **deprecates the Secure Credential Store** (SCS) plug-in used in Zowe V1. + - V2 introduces **team profiles** and **deprecates the Secure Credential Store** (SCS) plug-in used in Zowe V1. - Connection details can be managed efficiently within one file, promoting a global configuration that can be shared across teams and mainframe services. For more information on how to use profiles, see [Team configurations](https://docs.zowe.org/stable/user-guide/cli-using-using-team-profiles/) in Zowe Docs. - Secure credential encryption is included in the core CLI. + - V3 includes the preceding features. Additionally, deprecates support for Zowe V1 profiles. + + - To upgrade from an older Zowe release, see [Migrating from Zowe Vx to Zowe V3](https://docs.zowe.org/stable/whats-new/zowe-v3-migratio3). +
Don't see what you're looking for? Browse questions from the community or ask your own in the [Q&A section](https://github.com/zowe/zowe-cli/discussions/categories/q-a) of our repo. From 14986b155d573b376f23b9604d686f1c981ea9ee Mon Sep 17 00:00:00 2001 From: zowe-robot Date: Mon, 16 Dec 2024 16:59:40 +0000 Subject: [PATCH 45/61] Bump version to 8.9.1 [ci skip] Signed-off-by: zowe-robot --- lerna.json | 2 +- npm-shrinkwrap.json | 18 +++++++++--------- packages/cli/package.json | 8 ++++---- packages/workflows/package.json | 4 ++-- packages/zosfiles/CHANGELOG.md | 2 +- packages/zosfiles/package.json | 2 +- packages/zosjobs/package.json | 4 ++-- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lerna.json b/lerna.json index daa5c34cf9..8d7b46ef3a 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "8.9.0", + "version": "8.9.1", "command": { "publish": { "ignoreChanges": [ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 52e37e5113..2579acc821 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -16269,7 +16269,7 @@ }, "packages/cli": { "name": "@zowe/cli", - "version": "8.9.0", + "version": "8.9.1", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { @@ -16277,12 +16277,12 @@ "@zowe/imperative": "8.8.3", "@zowe/provisioning-for-zowe-sdk": "8.8.3", "@zowe/zos-console-for-zowe-sdk": "8.8.3", - "@zowe/zos-files-for-zowe-sdk": "8.9.0", - "@zowe/zos-jobs-for-zowe-sdk": "8.9.0", + "@zowe/zos-files-for-zowe-sdk": "8.9.1", + "@zowe/zos-jobs-for-zowe-sdk": "8.9.1", "@zowe/zos-logs-for-zowe-sdk": "8.8.3", "@zowe/zos-tso-for-zowe-sdk": "8.8.3", "@zowe/zos-uss-for-zowe-sdk": "8.8.3", - "@zowe/zos-workflows-for-zowe-sdk": "8.9.0", + "@zowe/zos-workflows-for-zowe-sdk": "8.9.1", "@zowe/zosmf-for-zowe-sdk": "8.8.3", "find-process": "1.4.7", "lodash": "4.17.21", @@ -16599,10 +16599,10 @@ }, "packages/workflows": { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "8.9.0", + "version": "8.9.1", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.9.0" + "@zowe/zos-files-for-zowe-sdk": "8.9.1" }, "devDependencies": { "@zowe/cli-test-utils": "8.8.3", @@ -16636,7 +16636,7 @@ }, "packages/zosfiles": { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "8.9.0", + "version": "8.9.1", "license": "EPL-2.0", "dependencies": { "lodash": "^4.17.21", @@ -16678,10 +16678,10 @@ }, "packages/zosjobs": { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "8.9.0", + "version": "8.9.1", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.9.0" + "@zowe/zos-files-for-zowe-sdk": "8.9.1" }, "devDependencies": { "@zowe/cli-test-utils": "8.8.3", diff --git a/packages/cli/package.json b/packages/cli/package.json index bfa9205e32..8e49ec1c10 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli", - "version": "8.9.0", + "version": "8.9.1", "zoweVersion": "v3.0.0", "description": "Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.", "author": "Zowe", @@ -62,12 +62,12 @@ "@zowe/imperative": "8.8.3", "@zowe/provisioning-for-zowe-sdk": "8.8.3", "@zowe/zos-console-for-zowe-sdk": "8.8.3", - "@zowe/zos-files-for-zowe-sdk": "8.9.0", - "@zowe/zos-jobs-for-zowe-sdk": "8.9.0", + "@zowe/zos-files-for-zowe-sdk": "8.9.1", + "@zowe/zos-jobs-for-zowe-sdk": "8.9.1", "@zowe/zos-logs-for-zowe-sdk": "8.8.3", "@zowe/zos-tso-for-zowe-sdk": "8.8.3", "@zowe/zos-uss-for-zowe-sdk": "8.8.3", - "@zowe/zos-workflows-for-zowe-sdk": "8.9.0", + "@zowe/zos-workflows-for-zowe-sdk": "8.9.1", "@zowe/zosmf-for-zowe-sdk": "8.8.3", "find-process": "1.4.7", "lodash": "4.17.21", diff --git a/packages/workflows/package.json b/packages/workflows/package.json index c32bf129ff..6bccd466ac 100644 --- a/packages/workflows/package.json +++ b/packages/workflows/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "8.9.0", + "version": "8.9.1", "description": "Zowe SDK to interact with the z/OS workflows APIs", "author": "Zowe", "license": "EPL-2.0", @@ -45,7 +45,7 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.9.0" + "@zowe/zos-files-for-zowe-sdk": "8.9.1" }, "devDependencies": { "@zowe/cli-test-utils": "8.8.3", diff --git a/packages/zosfiles/CHANGELOG.md b/packages/zosfiles/CHANGELOG.md index 33cdb9b9b7..3d8b3f6d79 100644 --- a/packages/zosfiles/CHANGELOG.md +++ b/packages/zosfiles/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Zowe z/OS files SDK package will be documented in this file. -## Recent Changes +## `8.9.1` - BugFix: Corrected the `apiResponse` response value from `streamToDataSet()`,`streamToUss()`,`bufferToUss()` and `bufferToDataSet()` on the Upload SDK. [#2381](https://github.com/zowe/zowe-cli/pull/2381) - BugFix: Corrected the `Upload.BufferToUssFile()` SDK function to properly tag uploaded files. [#2378](https://github.com/zowe/zowe-cli/pull/2378) diff --git a/packages/zosfiles/package.json b/packages/zosfiles/package.json index c5c305e508..d04f8d8499 100644 --- a/packages/zosfiles/package.json +++ b/packages/zosfiles/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "8.9.0", + "version": "8.9.1", "description": "Zowe SDK to interact with files and data sets on z/OS", "author": "Zowe", "license": "EPL-2.0", diff --git a/packages/zosjobs/package.json b/packages/zosjobs/package.json index 97b4a89bf0..17db41fd33 100644 --- a/packages/zosjobs/package.json +++ b/packages/zosjobs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "8.9.0", + "version": "8.9.1", "description": "Zowe SDK to interact with jobs on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -46,7 +46,7 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.9.0" + "@zowe/zos-files-for-zowe-sdk": "8.9.1" }, "devDependencies": { "@zowe/cli-test-utils": "8.8.3", From 73296b44d178365d5b438a047f9c54ba583eaecc Mon Sep 17 00:00:00 2001 From: jace-roell Date: Mon, 16 Dec 2024 12:39:12 -0500 Subject: [PATCH 46/61] system test fix Signed-off-by: jace-roell --- .../__system__/methods/upload/Upload.system.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts b/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts index adeaa4f699..744a2d4542 100644 --- a/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts +++ b/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts @@ -326,7 +326,7 @@ describe("Upload Data Set", () => { expect(error).toBeFalsy(); - expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "Buffer<>","to": dsname+"(TEST)"}); + expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "","to": dsname+"(TEST)"}); expect(Buffer.from(getResponse.toString().trim())).toEqual(data); }); @@ -349,7 +349,7 @@ describe("Upload Data Set", () => { expect(error).toBeFalsy(); - expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "Stream<>","to": dsname+"(TEST)"}); + expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "[Readable]","to": dsname+"(TEST)"}); expect(getResponse.toString().trim()).toEqual(testdata); }); @@ -793,7 +793,7 @@ describe("Upload USS file", () => { expect(error).toBeFalsy(); - expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "Buffer<>","to": ussname}); + expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "","to": ussname}); expect(getResponse).toEqual(Buffer.from(data.toString())); }); @@ -815,7 +815,7 @@ describe("Upload USS file", () => { expect(error).toBeFalsy(); - expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "Stream<>","to": ussname}); + expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "[Readable]","to": ussname}); expect(getResponse).toEqual(Buffer.from(testdata)); }); From 312c16c381930b34c70ea2e6431e6b7db8f1692f Mon Sep 17 00:00:00 2001 From: Rudy Flores <68666202+rudyflores@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:17:56 -0500 Subject: [PATCH 47/61] Add code coverage Signed-off-by: Rudy Flores <68666202+rudyflores@users.noreply.github.com> --- .../client/ProxySettings.unit.test.ts | 155 ++++++++++++++---- .../src/rest/src/client/ProxySettings.ts | 93 ++++++----- 2 files changed, 180 insertions(+), 68 deletions(-) diff --git a/packages/imperative/src/rest/__tests__/client/ProxySettings.unit.test.ts b/packages/imperative/src/rest/__tests__/client/ProxySettings.unit.test.ts index 952b9e298f..9aeb24ca7b 100644 --- a/packages/imperative/src/rest/__tests__/client/ProxySettings.unit.test.ts +++ b/packages/imperative/src/rest/__tests__/client/ProxySettings.unit.test.ts @@ -1,13 +1,13 @@ /* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Copyright Contributors to the Zowe Project. + * + */ import * as process from "process"; @@ -23,7 +23,7 @@ describe("Proxy tests", () => { const session = { hostname: "fake.com", port: 443, - rejectUnauthorized: false + rejectUnauthorized: false, } as ISession; const privateProxy = ProxySettings as any; const httpUrl = "http://www.zowe.com"; @@ -31,7 +31,9 @@ describe("Proxy tests", () => { const noProxyList = "www.zowe.com, fake.com,ibm.com,broadcom.com "; const passedUrl = "passedurl.com"; let getProxySettingsSpy: jest.SpyInstance; + let getProxyAuthSettingSpy: jest.SpyInstance; let checkUrlSpy: jest.SpyInstance; + let matchesNoProxySettingsSpy: jest.SpyInstance; describe("recognise passed proxy values in session", () => { const noProxySpy = jest.spyOn(privateProxy, "matchesNoProxySettings"); @@ -40,7 +42,7 @@ describe("Proxy tests", () => { checkUrlSpy = jest.spyOn(privateProxy, "checkUrl"); const expected = { proxyUrl: passedUrl, - protocol: HTTPS_PROTOCOL + protocol: HTTPS_PROTOCOL, }; beforeEach(() => { @@ -55,7 +57,9 @@ describe("Proxy tests", () => { expect(httpEnvVarSpy).not.toHaveBeenCalled(); expect(httpsEnvVarSpy).not.toHaveBeenCalled(); checkUrlSpy.mockReturnValueOnce(passedUrl); - expect(JSON.stringify(ProxySettings["getProxySettings"](session))).toEqual(JSON.stringify(expected)); + expect( + JSON.stringify(ProxySettings["getProxySettings"](session)) + ).toEqual(JSON.stringify(expected)); noProxySpy.mockClear(); checkUrlSpy.mockClear(); }); @@ -67,34 +71,89 @@ describe("Proxy tests", () => { expect(httpEnvVarSpy).not.toHaveBeenCalled(); expect(httpsEnvVarSpy).not.toHaveBeenCalled(); checkUrlSpy.mockReturnValueOnce(passedUrl); - expect(JSON.stringify(ProxySettings["getProxySettings"](session))).toEqual(JSON.stringify(expected)); + expect( + JSON.stringify(ProxySettings["getProxySettings"](session)) + ).toEqual(JSON.stringify(expected)); noProxySpy.mockClear(); checkUrlSpy.mockClear(); }); }); describe("getProxyAgent", () => { + const headers = { + "Proxy-Authorization": "Basic ==ThisIsATest123", + }; + beforeEach(() => { jest.clearAllMocks(); + jest.restoreAllMocks(); + jest.resetModules(); + jest.resetAllMocks(); getProxySettingsSpy = jest.spyOn(privateProxy, "getProxySettings"); + getProxyAuthSettingSpy = jest.spyOn( + privateProxy, + "getProxyAuthHeader" + ); }); it("Should retrieve the HTTP proxy agent", () => { - const expected = new HttpProxyAgent(httpUrl); + const expected = new HttpProxyAgent(httpUrl, { headers }); getProxySettingsSpy.mockReturnValue({ proxyUrl: httpUrl, - protocol: HTTP_PROTOCOL + protocol: HTTP_PROTOCOL, }); - expect(JSON.stringify(ProxySettings.getProxyAgent(session))).toEqual(JSON.stringify(expected)); + getProxyAuthSettingSpy.mockReturnValue(headers); + expect( + JSON.stringify(ProxySettings.getProxyAgent(session)) + ).toEqual(JSON.stringify(expected)); }); it("Should retrieve the HTTPS proxy agent", () => { - const expected = new HttpsProxyAgent(httpsUrl, { rejectUnauthorized: false }); + const expected = new HttpsProxyAgent(httpsUrl, { + rejectUnauthorized: false, + }); getProxySettingsSpy.mockReturnValue({ proxyUrl: httpsUrl, - protocol: HTTPS_PROTOCOL + protocol: HTTPS_PROTOCOL, }); - expect(JSON.stringify(ProxySettings.getProxyAgent(session))).toEqual(JSON.stringify(expected)); + expect( + JSON.stringify(ProxySettings.getProxyAgent(session)) + ).toEqual(JSON.stringify(expected)); + }); + + it("Should return undefined when a protocol is not defined in the session", () => { + const noProtocolSession = { ...session }; + noProtocolSession.protocol = undefined; + expect(ProxySettings.getProxyAgent(session)).toEqual(undefined); + }); + }); + + describe("getProxyAuthHeader", () => { + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + jest.resetModules(); + jest.resetAllMocks(); + }); + + it("Should retrieve the auth header from the proxy settings", () => { + const proxyAuthSetting = "Basic ==ThisIsATest123"; + expect( + ProxySettings["getProxyAuthHeader"]({ + authSetting: proxyAuthSetting, + proxyUrl: new URL("https://www.google.com/"), + protocol: HTTPS_PROTOCOL, + }) + ).toEqual({ "Proxy-Authorization": proxyAuthSetting }); + }); + + it("Should return undefined if the proxy auth setting is not in the proxy settings", () => { + expect( + ProxySettings["getProxyAuthHeader"]({ + proxyUrl: new URL("https://www.google.com/"), + protocol: HTTPS_PROTOCOL, + }) + ).toEqual(undefined); }); }); @@ -107,7 +166,7 @@ describe("Proxy tests", () => { it("Should retrieve the system proxy URL", () => { getProxySettingsSpy.mockReturnValue({ proxyUrl: httpsUrl, - protocol: HTTPS_PROTOCOL + protocol: HTTPS_PROTOCOL, }); expect(ProxySettings.getSystemProxyUrl(session)).toEqual(httpsUrl); }); @@ -116,16 +175,36 @@ describe("Proxy tests", () => { describe("getProxySettings", () => { beforeEach(() => { jest.clearAllMocks(); + jest.restoreAllMocks(); + jest.resetModules(); + jest.resetAllMocks(); checkUrlSpy = jest.spyOn(privateProxy, "checkUrl"); + matchesNoProxySettingsSpy = jest.spyOn( + privateProxy, + "matchesNoProxySettings" + ); }); it("Should return proxy settings from session", () => { const expected = { proxyUrl: httpsUrl, - protocol: HTTPS_PROTOCOL + protocol: HTTPS_PROTOCOL, + authSetting: "Basic ==ThisIsATest123", }; checkUrlSpy.mockReturnValue(httpsUrl); - expect(ProxySettings["getProxySettings"](session)).toEqual(expected); + session.proxy = { + proxy_authorization: "Basic ==ThisIsATest123", + }; + expect(ProxySettings["getProxySettings"](session)).toEqual( + expected + ); + }); + + it("Should return undefined proxy url matchesNoProxySettings", () => { + matchesNoProxySettingsSpy.mockReturnValue(true); + expect(ProxySettings["getProxySettings"](session)).toEqual( + undefined + ); }); }); @@ -143,28 +222,46 @@ describe("Proxy tests", () => { }); describe("matchesNoProxySettings", () => { - it("Should match session hostname with no_proxy", () => { + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + jest.resetModules(); + jest.resetAllMocks(); + }); + + it("Should match session hostname with no_proxy", () => { const expected = true; process.env["NO_PROXY"] = noProxyList; - expect(ProxySettings["matchesNoProxySettings"](session)).toEqual(expected); + expect(ProxySettings["matchesNoProxySettings"](session)).toEqual( + expected + ); process.env["NO_PROXY"] = undefined; }); it("Should return true for match with no_proxy passed with session proxy", () => { session.proxy = { http_proxy: passedUrl, no_proxy: ["fake.com"] }; session.protocol = HTTP_PROTOCOL; - expect(ProxySettings["matchesNoProxySettings"](session)).toEqual(true); + expect(ProxySettings["matchesNoProxySettings"](session)).toEqual( + true + ); }); - it("Should not match session hostname with no_proxy", () => { + it("Should not match session hostname with no_proxy", () => { const expected = false; process.env["NO_PROXY"] = noProxyList; session.hostname = "microsoft.com"; - expect(ProxySettings["matchesNoProxySettings"](session)).toEqual(expected); + expect(ProxySettings["matchesNoProxySettings"](session)).toEqual( + expected + ); process.env["NO_PROXY"] = undefined; }); it("Should return false for match with no_proxy passed with session proxy", () => { - session.proxy = { http_proxy: passedUrl, no_proxy: ["false.com", "blah.com"] }; + session.proxy = { + http_proxy: passedUrl, + no_proxy: ["false.com", "blah.com"], + }; session.protocol = HTTP_PROTOCOL; - expect(ProxySettings["matchesNoProxySettings"](session)).toEqual(false); + expect(ProxySettings["matchesNoProxySettings"](session)).toEqual( + false + ); }); }); }); diff --git a/packages/imperative/src/rest/src/client/ProxySettings.ts b/packages/imperative/src/rest/src/client/ProxySettings.ts index 6132e9e20b..c9cc78aaab 100644 --- a/packages/imperative/src/rest/src/client/ProxySettings.ts +++ b/packages/imperative/src/rest/src/client/ProxySettings.ts @@ -1,22 +1,26 @@ /* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Copyright Contributors to the Zowe Project. + * + */ -import { env } from 'process'; -import { URL } from 'url'; -import { Agent } from 'https'; -import { HttpProxyAgent } from 'http-proxy-agent'; -import { HttpsProxyAgent } from 'https-proxy-agent'; +import { env } from "process"; +import { URL } from "url"; +import { Agent } from "https"; +import { HttpProxyAgent } from "http-proxy-agent"; +import { HttpsProxyAgent } from "https-proxy-agent"; -import { HTTP_PROTOCOL_CHOICES, HTTP_PROTOCOL, HTTPS_PROTOCOL } from '../session/SessConstants'; -import { ISession } from '../session/doc/ISession'; +import { + HTTP_PROTOCOL_CHOICES, + HTTP_PROTOCOL, + HTTPS_PROTOCOL, +} from "../session/SessConstants"; +import { ISession } from "../session/doc/ISession"; /** * Utility class to provide an http agent to REST APIs that is configured for @@ -33,7 +37,6 @@ import { ISession } from '../session/doc/ISession'; * to match with the hostname of the Zowe profile. */ export class ProxySettings { - /** * Retrieve an appropriate http.agent instance if proxy environment variables can be found. * @static @@ -47,14 +50,18 @@ export class ProxySettings { const proxySetting = this.getProxySettings(session); const proxyOptions = {} as ProxyOptions; const authHeader = ProxySettings.getProxyAuthHeader(proxySetting); - if(authHeader) { + if (authHeader) { proxyOptions.headers = authHeader; } - if (proxySetting?.protocol === HTTP_PROTOCOL) { + if (!proxySetting?.protocol) { + return; + } + if (proxySetting.protocol === HTTP_PROTOCOL) { return new HttpProxyAgent(proxySetting.proxyUrl, proxyOptions); } - if (proxySetting?.protocol === HTTPS_PROTOCOL) { - proxyOptions.rejectUnauthorized = session.rejectUnauthorized ?? true; + if (proxySetting.protocol === HTTPS_PROTOCOL) { + proxyOptions.rejectUnauthorized = + session.rejectUnauthorized ?? true; return new HttpsProxyAgent(proxySetting.proxyUrl, proxyOptions); } } @@ -83,7 +90,8 @@ export class ProxySettings { * @memberof ProxySettings */ public static matchesNoProxySettings(session: ISession): boolean { - const noProxyValues = session.proxy?.no_proxy ?? this.getNoProxyEnvVariables(); + const noProxyValues = + session.proxy?.no_proxy ?? this.getNoProxyEnvVariables(); if (!noProxyValues) { return false; } @@ -93,10 +101,12 @@ export class ProxySettings { return false; } - private static getProxyAuthHeader(proxySetting: ProxySetting): { [key: string]: string } | undefined { - return proxySetting.authSetting - ? { 'Proxy-Authorization': proxySetting.authSetting } - : undefined; + private static getProxyAuthHeader( + proxySetting: ProxySetting + ): { [key: string]: string } | undefined { + return proxySetting?.authSetting + ? { "Proxy-Authorization": proxySetting.authSetting } + : undefined; } /** @@ -107,26 +117,29 @@ export class ProxySettings { * @returns instance of private `ProxySetting` or `undefined` * @memberof ProxySettings */ - private static getProxySettings(session: ISession): ProxySetting | undefined { + private static getProxySettings( + session: ISession + ): ProxySetting | undefined { if (this.matchesNoProxySettings(session)) { return; } const protocol = session.protocol ?? HTTPS_PROTOCOL; let envVariable: string | undefined; if (protocol === HTTP_PROTOCOL) { - envVariable = session.proxy?.http_proxy ?? this.getHttpEnvVariables(); - } - else if (protocol === HTTPS_PROTOCOL) { - envVariable = session.proxy?.https_proxy ?? this.getHttpsEnvVariables(); + envVariable = + session.proxy?.http_proxy ?? this.getHttpEnvVariables(); + } else if (protocol === HTTPS_PROTOCOL) { + envVariable = + session.proxy?.https_proxy ?? this.getHttpsEnvVariables(); } const proxyUrl = this.checkUrl(envVariable); const authSetting = session.proxy?.proxy_authorization; if (authSetting) { - return {proxyUrl, protocol, authSetting}; + return { proxyUrl, protocol, authSetting }; } if (proxyUrl) { - return {proxyUrl, protocol}; + return { proxyUrl, protocol }; } } @@ -165,7 +178,9 @@ export class ProxySettings { if (!noProxyValue) { return; } - return noProxyValue.split(',').map(entry => entry.trim().toLocaleLowerCase()); + return noProxyValue + .split(",") + .map((entry) => entry.trim().toLocaleLowerCase()); } /** @@ -189,12 +204,12 @@ export class ProxySettings { * Internal interface to group proxy settings */ interface ProxySetting { - proxyUrl: URL, - protocol: HTTP_PROTOCOL_CHOICES, - authSetting?: string + proxyUrl: URL; + protocol: HTTP_PROTOCOL_CHOICES; + authSetting?: string; } interface ProxyOptions { - headers?: { [key: string]: string }, - rejectUnauthorized?: boolean + headers?: { [key: string]: string }; + rejectUnauthorized?: boolean; } From d90f8c05aae04fe06407b2089c1de206721d937b Mon Sep 17 00:00:00 2001 From: Rudy Flores <68666202+rudyflores@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:19:12 -0500 Subject: [PATCH 48/61] Update code formatting Signed-off-by: Rudy Flores <68666202+rudyflores@users.noreply.github.com> --- .../client/ProxySettings.unit.test.ts | 18 +++++++++--------- .../src/rest/src/client/ProxySettings.ts | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/imperative/src/rest/__tests__/client/ProxySettings.unit.test.ts b/packages/imperative/src/rest/__tests__/client/ProxySettings.unit.test.ts index 9aeb24ca7b..f6ff5aac4c 100644 --- a/packages/imperative/src/rest/__tests__/client/ProxySettings.unit.test.ts +++ b/packages/imperative/src/rest/__tests__/client/ProxySettings.unit.test.ts @@ -1,13 +1,13 @@ /* - * This program and the accompanying materials are made available under the terms of the - * Eclipse Public License v2.0 which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-v20.html - * - * SPDX-License-Identifier: EPL-2.0 - * - * Copyright Contributors to the Zowe Project. - * - */ +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ import * as process from "process"; diff --git a/packages/imperative/src/rest/src/client/ProxySettings.ts b/packages/imperative/src/rest/src/client/ProxySettings.ts index c9cc78aaab..56b8438d3f 100644 --- a/packages/imperative/src/rest/src/client/ProxySettings.ts +++ b/packages/imperative/src/rest/src/client/ProxySettings.ts @@ -1,13 +1,13 @@ /* - * This program and the accompanying materials are made available under the terms of the - * Eclipse Public License v2.0 which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-v20.html - * - * SPDX-License-Identifier: EPL-2.0 - * - * Copyright Contributors to the Zowe Project. - * - */ +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ import { env } from "process"; import { URL } from "url"; From dbee8155d630754433e4081a3851518d4abf3230 Mon Sep 17 00:00:00 2001 From: anaxceron Date: Mon, 16 Dec 2024 14:20:32 -0500 Subject: [PATCH 49/61] edit per adam feedback Signed-off-by: anaxceron --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b8a9c0c926..96ffb1047c 100644 --- a/README.md +++ b/README.md @@ -229,7 +229,7 @@ npm run test:system - Secure credential encryption is included in the core CLI. - - V3 includes the preceding features. Additionally, deprecates support for Zowe V1 profiles. + - V3 includes the preceding features. Additionally, removes support for Zowe V1 profiles. - To upgrade from an older Zowe release, see [Migrating from Zowe Vx to Zowe V3](https://docs.zowe.org/stable/whats-new/zowe-v3-migratio3). From b7a9da3bc941f028b854b71d276ed09932597433 Mon Sep 17 00:00:00 2001 From: Rudy Flores <68666202+rudyflores@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:25:26 -0500 Subject: [PATCH 50/61] Update CHANGELOG.md Signed-off-by: Rudy Flores <68666202+rudyflores@users.noreply.github.com> --- packages/imperative/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index 52915b7f41..e2a4a0c96f 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -6,7 +6,7 @@ All notable changes to the Imperative package will be documented in this file. - BugFix: Modified 8.8.2 bugfix to correct web help alias. [#2361](https://github.com/zowe/zowe-cli/pull/2361) - BugFix: Resolved issue where special characters could be corrupted when downloading a large file. [#2366](https://github.com/zowe/zowe-cli/pull/2366) -- BugFix: Modified location of Proxy-Authorization header to be located in the agent instead of the request. +- BugFix: Modified location of Proxy-Authorization header to be located in the agent instead of the request. [#2389](https://github.com/zowe/zowe-cli/issues/2389) ## `8.8.2` From c0c27c135179fe979a3efa48447bdf50d946231a Mon Sep 17 00:00:00 2001 From: Rudy Flores <68666202+rudyflores@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:34:37 -0500 Subject: [PATCH 51/61] Update CHANGELOG.md Signed-off-by: Rudy Flores <68666202+rudyflores@users.noreply.github.com> --- packages/imperative/CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index e2a4a0c96f..2e6f0212a5 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,11 +2,14 @@ All notable changes to the Imperative package will be documented in this file. +## Recent Changes + +- BugFix: Modified location of Proxy-Authorization header to be located in the agent instead of the request. [#2389](https://github.com/zowe/zowe-cli/issues/2389) + ## `8.8.3` - BugFix: Modified 8.8.2 bugfix to correct web help alias. [#2361](https://github.com/zowe/zowe-cli/pull/2361) - BugFix: Resolved issue where special characters could be corrupted when downloading a large file. [#2366](https://github.com/zowe/zowe-cli/pull/2366) -- BugFix: Modified location of Proxy-Authorization header to be located in the agent instead of the request. [#2389](https://github.com/zowe/zowe-cli/issues/2389) ## `8.8.2` From 903fa3055e19417fc0102e52e02bbab0efb025d7 Mon Sep 17 00:00:00 2001 From: Pujal Gandhi <71276682+pujal0909@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:50:14 -0500 Subject: [PATCH 52/61] Update packages/zosfiles/CHANGELOG.md Co-authored-by: Trae Yelovich Signed-off-by: Pujal Gandhi <71276682+pujal0909@users.noreply.github.com> --- packages/zosfiles/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/zosfiles/CHANGELOG.md b/packages/zosfiles/CHANGELOG.md index 52ed872de6..50a6326d17 100644 --- a/packages/zosfiles/CHANGELOG.md +++ b/packages/zosfiles/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to the Zowe z/OS files SDK package will be documented in this file. ## Recent Changes -- Enhancement: The `Copy.dataset` method now recognizes partioned data sets and can copy members of a source PDS into an existing target PDS. [#2386](https://github.com/zowe/zowe-cli/pull/2386) +- Enhancement: The `Copy.dataset` method now recognizes partitioned data sets and can copy members of a source PDS into an existing target PDS. [#2386](https://github.com/zowe/zowe-cli/pull/2386) ## `8.9.1` From 1ae21230fabf8580cd842f263f2b8146ac776f2c Mon Sep 17 00:00:00 2001 From: jace-roell Date: Mon, 16 Dec 2024 15:55:06 -0500 Subject: [PATCH 53/61] changelog Signed-off-by: jace-roell --- packages/imperative/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index 52045f1d05..8531bdc5ca 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to the Imperative package will be documented in this file. ## Recent Changes -- BugFix: Resolved issue where team config base profiles were being overwritten if a user config did not have a base profile. [#2383](https://github.com/zowe/zowe-cli/pull/2383) +- BugFix: Resolved an issue where base profiles in a team configuration file were overwritten when a user configuration file did not include a base profile. [#2383](https://github.com/zowe/zowe-cli/pull/2383) ## `8.8.3` From c2a618cb5c245ba2d9d7f92678bcdbb4d4acf234 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Mon, 16 Dec 2024 15:57:24 -0500 Subject: [PATCH 54/61] linting Signed-off-by: jace-roell --- .../methods/upload/Upload.system.test.ts | 6 +++++- .../methods/upload/Upload.unit.test.ts | 1 - packages/zosfiles/src/methods/upload/Upload.ts | 18 ++++++++++++++---- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts b/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts index 744a2d4542..b93d74db4c 100644 --- a/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts +++ b/packages/zosfiles/__tests__/__system__/methods/upload/Upload.system.test.ts @@ -326,7 +326,11 @@ describe("Upload Data Set", () => { expect(error).toBeFalsy(); - expect(uploadResponse.apiResponse).toMatchObject({"success": true, "from": "","to": dsname+"(TEST)"}); + expect(uploadResponse.apiResponse).toMatchObject({ + success: true, + from: "", + to: dsname + "(TEST)", + }); expect(Buffer.from(getResponse.toString().trim())).toEqual(data); }); diff --git a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts index c0f92eb905..3e758ae690 100644 --- a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts +++ b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts @@ -22,7 +22,6 @@ import { IUploadOptions } from "../../../../src/methods/upload/doc/IUploadOption import { Upload } from "../../../../src/methods/upload/Upload"; import { List } from "../../../../src/methods/list/List"; import { Utilities } from "../../../../src/methods/utilities/Utilities"; -import { inspect } from "util"; import { ZosFilesUtils } from "../../../../src/utils/ZosFilesUtils"; import { stripNewLines } from "../../../../../../__tests__/__src__/TestUtils"; import { Create } from "../../../../src/methods/create"; diff --git a/packages/zosfiles/src/methods/upload/Upload.ts b/packages/zosfiles/src/methods/upload/Upload.ts index 9301c81bfc..af363ef988 100644 --- a/packages/zosfiles/src/methods/upload/Upload.ts +++ b/packages/zosfiles/src/methods/upload/Upload.ts @@ -187,8 +187,13 @@ export class Upload { // By default, apiResponse is empty when uploading const apiResponse: any = { success: true, - from: fileBuffer.length > maxBufferPreviewSize ? inspect(fileBuffer.subarray(0, maxBufferPreviewSize)).slice(0, -1) + "...>" : inspect(fileBuffer), - to: dataSetName + from: + fileBuffer.length > maxBufferPreviewSize + ? inspect( + fileBuffer.subarray(0, maxBufferPreviewSize) + ).slice(0, -1) + "...>" + : inspect(fileBuffer), + to: dataSetName, }; // Return Etag in apiResponse, if requested @@ -493,8 +498,13 @@ export class Upload { // By default, apiResponse is empty when uploading const apiResponse: any = { success: true, - from: fileBuffer.length > maxBufferPreviewSize ? inspect(fileBuffer.subarray(0, maxBufferPreviewSize)).slice(0, -1) + "...>" : inspect(fileBuffer), - to: origUssname + from: + fileBuffer.length > maxBufferPreviewSize + ? inspect( + fileBuffer.subarray(0, maxBufferPreviewSize) + ).slice(0, -1) + "...>" + : inspect(fileBuffer), + to: origUssname, }; // Return Etag in apiResponse, if requested From c9c4ab8bff4b18fc3924f1ba07fe860aaaf1bf53 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Tue, 17 Dec 2024 10:09:00 -0500 Subject: [PATCH 55/61] Generalize hard-link advice. Signed-off-by: Gene Johnston --- prototypes/Readme.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/prototypes/Readme.md b/prototypes/Readme.md index a8121f6ec7..763191fe3d 100644 --- a/prototypes/Readme.md +++ b/prototypes/Readme.md @@ -4,4 +4,8 @@ During experiments, you might place a new class into a particular package to con You do not want this new code to cause Zowe build pipelines to fail, but you do not want to lose the useful work that has been completed. Placing your source file(s) under the **prototypes** directory is a way to keep your valuable experiment and not break the Zowe build process. -Place your source file into a path under the **prototypes** directory that mirrors the real directory path . Personally, I like to create a hard link from the file in my real file path to an identical file path under the **prototypes** directory. That way I can import, compile, and debug in the real directory until I complete experiments. Before committing, I can just delete the file in the real directory path and the remaining hard-linked file in the **prototypes** directory path will have all of the latest changes. +Place your source file into a path under the **prototypes** directory that mirrors the real directory path. + +**Tip:** Create a hard link from the file in the real file path to an identical file path under the **prototypes** directory. That way imports, compiles, and debugging will work in the real directory during experiments, while all changes are automatically recorded in the **prototypes** path. + +**Note:** Remember to delete a new file or revert an existing file in the real directory path. The remaining hard-linked file(s) in the **prototypes** directory path will still have all of the latest changes. From 5b85f223c3ed69efd26983b722a3b2eedd5c28e7 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Tue, 17 Dec 2024 15:54:03 -0500 Subject: [PATCH 56/61] user config osLoc fix and unit test Signed-off-by: jace-roell --- .../config/__tests__/ProfileInfo.TeamConfig.unit.test.ts | 9 ++++++++- packages/imperative/src/config/src/ProfileInfo.ts | 4 ---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index 1ed8dd659d..8732ef1399 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -677,7 +677,14 @@ describe("TeamConfig ProfileInfo tests", () => { expect(arg.argValue).toEqual(expectedArgs[idx].argValue); expect(arg.argLoc.locType).toBe(ProfLocType.TEAM_CONFIG); expect(arg.argLoc.jsonLoc).toMatch(/^profiles\.(base_glob|LPAR2_home)\.properties\./); - expect(arg.argLoc.osLoc[0]).toEqual(path.normalize(path.join(teamHomeProjDir, `${testAppNm}.config.json`))); + expect([ + path.normalize( + path.join(teamHomeProjDir, `${testAppNm}.config.json`) + ), + path.normalize( + path.join(teamProjDir, `${testAppNm}.config.json`) + ), + ]).toContain(arg.argLoc.osLoc[0]); } }); diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index dd0c771161..e65a079e28 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1654,16 +1654,12 @@ export class ProfileInfo { }; let filePath: string; - if (_isPropInLayer(opts.configProperties) && opts.osLocInfo) { - filePath = opts.osLocInfo.path; - } else { for (const layer of this.mLoadedConfig.mLayers) { // Find the first layer that includes the JSON path if (_isPropInLayer(layer.properties)) { filePath = layer.path; break; } - } } return [{ From 9220a1020a5b1cb9974a3f4ea4bb3a1d38a481aa Mon Sep 17 00:00:00 2001 From: zowe-robot Date: Tue, 17 Dec 2024 21:48:50 +0000 Subject: [PATCH 57/61] Bump version to 8.10.0 [ci skip] Signed-off-by: zowe-robot --- .../__packages__/cli-test-utils/package.json | 4 +- lerna.json | 2 +- npm-shrinkwrap.json | 116 +++++++++--------- packages/cli/CHANGELOG.md | 2 +- packages/cli/package.json | 26 ++-- packages/core/package.json | 6 +- packages/imperative/CHANGELOG.md | 2 +- packages/imperative/package.json | 2 +- packages/provisioning/package.json | 8 +- packages/workflows/package.json | 10 +- packages/zosconsole/package.json | 8 +- packages/zosfiles/CHANGELOG.md | 2 +- packages/zosfiles/package.json | 10 +- packages/zosjobs/package.json | 10 +- packages/zoslogs/package.json | 8 +- packages/zosmf/package.json | 8 +- packages/zostso/package.json | 10 +- packages/zosuss/package.json | 6 +- 18 files changed, 120 insertions(+), 120 deletions(-) diff --git a/__tests__/__packages__/cli-test-utils/package.json b/__tests__/__packages__/cli-test-utils/package.json index 955e3b2ebc..e9f85b05d8 100644 --- a/__tests__/__packages__/cli-test-utils/package.json +++ b/__tests__/__packages__/cli-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli-test-utils", - "version": "8.8.3", + "version": "8.10.0", "description": "Test utilities package for Zowe CLI plug-ins", "author": "Zowe", "license": "EPL-2.0", @@ -43,7 +43,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.9", "@types/uuid": "^10.0.0", - "@zowe/imperative": "8.8.3" + "@zowe/imperative": "8.10.0" }, "peerDependencies": { "@zowe/imperative": "^8.0.0" diff --git a/lerna.json b/lerna.json index 8d7b46ef3a..20d40cb3b5 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "8.9.1", + "version": "8.10.0", "command": { "publish": { "ignoreChanges": [ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 2579acc821..486f42b2ad 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -52,7 +52,7 @@ }, "__tests__/__packages__/cli-test-utils": { "name": "@zowe/cli-test-utils", - "version": "8.8.3", + "version": "8.10.0", "license": "EPL-2.0", "dependencies": { "find-up": "^5.0.0", @@ -63,7 +63,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.9", "@types/uuid": "^10.0.0", - "@zowe/imperative": "8.8.3" + "@zowe/imperative": "8.10.0" }, "peerDependencies": { "@zowe/imperative": "^8.0.0" @@ -16269,21 +16269,21 @@ }, "packages/cli": { "name": "@zowe/cli", - "version": "8.9.1", + "version": "8.10.0", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3", - "@zowe/provisioning-for-zowe-sdk": "8.8.3", - "@zowe/zos-console-for-zowe-sdk": "8.8.3", - "@zowe/zos-files-for-zowe-sdk": "8.9.1", - "@zowe/zos-jobs-for-zowe-sdk": "8.9.1", - "@zowe/zos-logs-for-zowe-sdk": "8.8.3", - "@zowe/zos-tso-for-zowe-sdk": "8.8.3", - "@zowe/zos-uss-for-zowe-sdk": "8.8.3", - "@zowe/zos-workflows-for-zowe-sdk": "8.9.1", - "@zowe/zosmf-for-zowe-sdk": "8.8.3", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0", + "@zowe/provisioning-for-zowe-sdk": "8.10.0", + "@zowe/zos-console-for-zowe-sdk": "8.10.0", + "@zowe/zos-files-for-zowe-sdk": "8.10.0", + "@zowe/zos-jobs-for-zowe-sdk": "8.10.0", + "@zowe/zos-logs-for-zowe-sdk": "8.10.0", + "@zowe/zos-tso-for-zowe-sdk": "8.10.0", + "@zowe/zos-uss-for-zowe-sdk": "8.10.0", + "@zowe/zos-workflows-for-zowe-sdk": "8.10.0", + "@zowe/zosmf-for-zowe-sdk": "8.10.0", "find-process": "1.4.7", "lodash": "4.17.21", "minimatch": "9.0.5", @@ -16296,7 +16296,7 @@ "@types/diff": "^5.0.9", "@types/lodash": "^4.17.6", "@types/tar": "^6.1.11", - "@zowe/cli-test-utils": "8.8.3", + "@zowe/cli-test-utils": "8.10.0", "comment-json": "^4.2.3", "strip-ansi": "^6.0.1", "which": "^4.0.0" @@ -16352,15 +16352,15 @@ }, "packages/core": { "name": "@zowe/core-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "license": "EPL-2.0", "dependencies": { "comment-json": "~4.2.3", "string-width": "^4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/imperative": "8.10.0" }, "engines": { "node": ">=18.12.0" @@ -16371,7 +16371,7 @@ }, "packages/imperative": { "name": "@zowe/imperative", - "version": "8.8.3", + "version": "8.10.0", "license": "EPL-2.0", "dependencies": { "@types/yargs": "^17.0.32", @@ -16565,16 +16565,16 @@ }, "packages/provisioning": { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "license": "EPL-2.0", "dependencies": { "js-yaml": "^4.1.0" }, "devDependencies": { "@types/js-yaml": "^4.0.9", - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "engines": { "node": ">=18.12.0" @@ -16599,15 +16599,15 @@ }, "packages/workflows": { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "8.9.1", + "version": "8.10.0", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.9.1" + "@zowe/zos-files-for-zowe-sdk": "8.10.0" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "engines": { "node": ">=18.12.0" @@ -16619,12 +16619,12 @@ }, "packages/zosconsole": { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "engines": { "node": ">=18.12.0" @@ -16636,17 +16636,17 @@ }, "packages/zosfiles": { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "8.9.1", + "version": "8.10.0", "license": "EPL-2.0", "dependencies": { "lodash": "^4.17.21", "minimatch": "^9.0.5" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3", - "@zowe/zos-uss-for-zowe-sdk": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0", + "@zowe/zos-uss-for-zowe-sdk": "8.10.0" }, "engines": { "node": ">=18.12.0" @@ -16678,15 +16678,15 @@ }, "packages/zosjobs": { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "8.9.1", + "version": "8.10.0", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.9.1" + "@zowe/zos-files-for-zowe-sdk": "8.10.0" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "engines": { "node": ">=18.12.0" @@ -16698,12 +16698,12 @@ }, "packages/zoslogs": { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "engines": { "node": ">=18.12.0" @@ -16715,12 +16715,12 @@ }, "packages/zosmf": { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "engines": { "node": ">=18.12.0" @@ -16732,15 +16732,15 @@ }, "packages/zostso": { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "license": "EPL-2.0", "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "8.8.3" + "@zowe/zosmf-for-zowe-sdk": "8.10.0" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "engines": { "node": ">=18.12.0" @@ -16752,15 +16752,15 @@ }, "packages/zosuss": { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "license": "EPL-2.0", "dependencies": { "ssh2": "^1.15.0" }, "devDependencies": { "@types/ssh2": "^1.11.19", - "@zowe/cli-test-utils": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/imperative": "8.10.0" }, "engines": { "node": ">=18.12.0" diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 979fb828ea..0533d487e2 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,7 +1,7 @@ # Change Log All notable changes to the Zowe CLI package will be documented in this file. -## Recent Changes +## `8.10.0` -Enhancement: The `zowe zos-files copy data-set` command now copies members from a source partitioned data set to an existing target partitioned data set.[#2386](https://github.com/zowe/zowe-cli/pull/2386) ## `8.9.0` diff --git a/packages/cli/package.json b/packages/cli/package.json index 8e49ec1c10..6f4a7fec69 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli", - "version": "8.9.1", + "version": "8.10.0", "zoweVersion": "v3.0.0", "description": "Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.", "author": "Zowe", @@ -58,17 +58,17 @@ "preshrinkwrap": "node ../../scripts/rewriteShrinkwrap.js" }, "dependencies": { - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3", - "@zowe/provisioning-for-zowe-sdk": "8.8.3", - "@zowe/zos-console-for-zowe-sdk": "8.8.3", - "@zowe/zos-files-for-zowe-sdk": "8.9.1", - "@zowe/zos-jobs-for-zowe-sdk": "8.9.1", - "@zowe/zos-logs-for-zowe-sdk": "8.8.3", - "@zowe/zos-tso-for-zowe-sdk": "8.8.3", - "@zowe/zos-uss-for-zowe-sdk": "8.8.3", - "@zowe/zos-workflows-for-zowe-sdk": "8.9.1", - "@zowe/zosmf-for-zowe-sdk": "8.8.3", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0", + "@zowe/provisioning-for-zowe-sdk": "8.10.0", + "@zowe/zos-console-for-zowe-sdk": "8.10.0", + "@zowe/zos-files-for-zowe-sdk": "8.10.0", + "@zowe/zos-jobs-for-zowe-sdk": "8.10.0", + "@zowe/zos-logs-for-zowe-sdk": "8.10.0", + "@zowe/zos-tso-for-zowe-sdk": "8.10.0", + "@zowe/zos-uss-for-zowe-sdk": "8.10.0", + "@zowe/zos-workflows-for-zowe-sdk": "8.10.0", + "@zowe/zosmf-for-zowe-sdk": "8.10.0", "find-process": "1.4.7", "lodash": "4.17.21", "minimatch": "9.0.5", @@ -78,7 +78,7 @@ "@types/diff": "^5.0.9", "@types/lodash": "^4.17.6", "@types/tar": "^6.1.11", - "@zowe/cli-test-utils": "8.8.3", + "@zowe/cli-test-utils": "8.10.0", "comment-json": "^4.2.3", "strip-ansi": "^6.0.1", "which": "^4.0.0" diff --git a/packages/core/package.json b/packages/core/package.json index abc273e430..bd4db2f727 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/core-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "description": "Core libraries shared by Zowe SDK packages", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ "string-width": "^4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/imperative": "8.10.0" }, "peerDependencies": { "@zowe/imperative": "^8.0.0" diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index 2e6f0212a5..06395afdc1 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Imperative package will be documented in this file. -## Recent Changes +## `8.10.0` - BugFix: Modified location of Proxy-Authorization header to be located in the agent instead of the request. [#2389](https://github.com/zowe/zowe-cli/issues/2389) diff --git a/packages/imperative/package.json b/packages/imperative/package.json index 6b197330b6..addb75bd41 100644 --- a/packages/imperative/package.json +++ b/packages/imperative/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/imperative", - "version": "8.8.3", + "version": "8.10.0", "description": "framework for building configurable CLIs", "author": "Zowe", "license": "EPL-2.0", diff --git a/packages/provisioning/package.json b/packages/provisioning/package.json index 74ba89c9c2..2453327ebf 100644 --- a/packages/provisioning/package.json +++ b/packages/provisioning/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "description": "Zowe SDK to interact with the z/OS provisioning APIs", "author": "Zowe", "license": "EPL-2.0", @@ -49,9 +49,9 @@ }, "devDependencies": { "@types/js-yaml": "^4.0.9", - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/workflows/package.json b/packages/workflows/package.json index 6bccd466ac..696c7bf8b8 100644 --- a/packages/workflows/package.json +++ b/packages/workflows/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "8.9.1", + "version": "8.10.0", "description": "Zowe SDK to interact with the z/OS workflows APIs", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.9.1" + "@zowe/zos-files-for-zowe-sdk": "8.10.0" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zosconsole/package.json b/packages/zosconsole/package.json index cd8be18e9c..1f0e7d4dad 100644 --- a/packages/zosconsole/package.json +++ b/packages/zosconsole/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "description": "Zowe SDK to interact with the z/OS console", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zosfiles/CHANGELOG.md b/packages/zosfiles/CHANGELOG.md index 50a6326d17..739c33feaa 100644 --- a/packages/zosfiles/CHANGELOG.md +++ b/packages/zosfiles/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Zowe z/OS files SDK package will be documented in this file. -## Recent Changes +## `8.10.0` - Enhancement: The `Copy.dataset` method now recognizes partitioned data sets and can copy members of a source PDS into an existing target PDS. [#2386](https://github.com/zowe/zowe-cli/pull/2386) ## `8.9.1` diff --git a/packages/zosfiles/package.json b/packages/zosfiles/package.json index d04f8d8499..27302db5f8 100644 --- a/packages/zosfiles/package.json +++ b/packages/zosfiles/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "8.9.1", + "version": "8.10.0", "description": "Zowe SDK to interact with files and data sets on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -50,10 +50,10 @@ "minimatch": "^9.0.5" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3", - "@zowe/zos-uss-for-zowe-sdk": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0", + "@zowe/zos-uss-for-zowe-sdk": "8.10.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zosjobs/package.json b/packages/zosjobs/package.json index 17db41fd33..d403fdb683 100644 --- a/packages/zosjobs/package.json +++ b/packages/zosjobs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "8.9.1", + "version": "8.10.0", "description": "Zowe SDK to interact with jobs on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -46,12 +46,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.9.1" + "@zowe/zos-files-for-zowe-sdk": "8.10.0" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zoslogs/package.json b/packages/zoslogs/package.json index 954d6aa8cb..4d5cce70e9 100644 --- a/packages/zoslogs/package.json +++ b/packages/zoslogs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "description": "Zowe SDK to interact with the z/OS logs", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zosmf/package.json b/packages/zosmf/package.json index 1dee4b9536..fa09136aa6 100644 --- a/packages/zosmf/package.json +++ b/packages/zosmf/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "description": "Zowe SDK to interact with the z/OS Management Facility", "author": "Zowe", "license": "EPL-2.0", @@ -44,9 +44,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zostso/package.json b/packages/zostso/package.json index 92baabc181..41a72be750 100644 --- a/packages/zostso/package.json +++ b/packages/zostso/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "description": "Zowe SDK to interact with TSO on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "8.8.3" + "@zowe/zosmf-for-zowe-sdk": "8.10.0" }, "devDependencies": { - "@zowe/cli-test-utils": "8.8.3", - "@zowe/core-for-zowe-sdk": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.0", + "@zowe/imperative": "8.10.0" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zosuss/package.json b/packages/zosuss/package.json index 70da59fb65..60e7ffbd0a 100644 --- a/packages/zosuss/package.json +++ b/packages/zosuss/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "8.8.3", + "version": "8.10.0", "description": "Zowe SDK to interact with USS on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ }, "devDependencies": { "@types/ssh2": "^1.11.19", - "@zowe/cli-test-utils": "8.8.3", - "@zowe/imperative": "8.8.3" + "@zowe/cli-test-utils": "8.10.0", + "@zowe/imperative": "8.10.0" }, "peerDependencies": { "@zowe/imperative": "^8.0.0" From e2f465cdf5cd6cf8122257cb6273e65ee0cb1464 Mon Sep 17 00:00:00 2001 From: jace-roell Date: Wed, 18 Dec 2024 09:57:24 -0500 Subject: [PATCH 58/61] linting warnings Signed-off-by: jace-roell --- file.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 file.ts diff --git a/file.ts b/file.ts new file mode 100644 index 0000000000..70ab34a41b --- /dev/null +++ b/file.ts @@ -0,0 +1,8 @@ +const { ProfileInfo } = require("@zowe/imperative"); +(async () => { + const profInfo = new ProfileInfo("zowe"); + await profInfo.readProfilesFromDisk(); + const upd = { profileName: "lpar1.test", profileType: "zosmf" }; + await profInfo.updateProperty({ ...upd, property: "user", value: "abc", setSecure: false }); + await profInfo.updateProperty({ ...upd, property: "password", value: "aa", setSecure: false }); +})(); \ No newline at end of file From 95a3fdd83a4ed39a97c9f426fcdba505218b136c Mon Sep 17 00:00:00 2001 From: jace-roell Date: Wed, 18 Dec 2024 09:59:06 -0500 Subject: [PATCH 59/61] rm dummy file and fix linting Signed-off-by: jace-roell --- file.ts | 8 -------- packages/imperative/src/config/src/ProfileInfo.ts | 12 ++++++------ 2 files changed, 6 insertions(+), 14 deletions(-) delete mode 100644 file.ts diff --git a/file.ts b/file.ts deleted file mode 100644 index 70ab34a41b..0000000000 --- a/file.ts +++ /dev/null @@ -1,8 +0,0 @@ -const { ProfileInfo } = require("@zowe/imperative"); -(async () => { - const profInfo = new ProfileInfo("zowe"); - await profInfo.readProfilesFromDisk(); - const upd = { profileName: "lpar1.test", profileType: "zosmf" }; - await profInfo.updateProperty({ ...upd, property: "user", value: "abc", setSecure: false }); - await profInfo.updateProperty({ ...upd, property: "password", value: "aa", setSecure: false }); -})(); \ No newline at end of file diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index e65a079e28..978a34cd9b 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -1654,12 +1654,12 @@ export class ProfileInfo { }; let filePath: string; - for (const layer of this.mLoadedConfig.mLayers) { - // Find the first layer that includes the JSON path - if (_isPropInLayer(layer.properties)) { - filePath = layer.path; - break; - } + for (const layer of this.mLoadedConfig.mLayers) { + // Find the first layer that includes the JSON path + if (_isPropInLayer(layer.properties)) { + filePath = layer.path; + break; + } } return [{ From 70213e1d9f4ca00b639cb75078dc7a18306dc83b Mon Sep 17 00:00:00 2001 From: zowe-robot Date: Wed, 18 Dec 2024 16:07:32 +0000 Subject: [PATCH 60/61] Bump version to 8.10.1 [ci skip] Signed-off-by: zowe-robot --- .../__packages__/cli-test-utils/package.json | 4 +- lerna.json | 2 +- npm-shrinkwrap.json | 116 +++++++++--------- packages/cli/package.json | 26 ++-- packages/core/package.json | 6 +- packages/imperative/CHANGELOG.md | 2 +- packages/imperative/package.json | 2 +- packages/provisioning/package.json | 8 +- packages/workflows/package.json | 10 +- packages/zosconsole/package.json | 8 +- packages/zosfiles/package.json | 10 +- packages/zosjobs/package.json | 10 +- packages/zoslogs/package.json | 8 +- packages/zosmf/package.json | 8 +- packages/zostso/package.json | 10 +- packages/zosuss/package.json | 6 +- 16 files changed, 118 insertions(+), 118 deletions(-) diff --git a/__tests__/__packages__/cli-test-utils/package.json b/__tests__/__packages__/cli-test-utils/package.json index e9f85b05d8..41c25d94fe 100644 --- a/__tests__/__packages__/cli-test-utils/package.json +++ b/__tests__/__packages__/cli-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli-test-utils", - "version": "8.10.0", + "version": "8.10.1", "description": "Test utilities package for Zowe CLI plug-ins", "author": "Zowe", "license": "EPL-2.0", @@ -43,7 +43,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.9", "@types/uuid": "^10.0.0", - "@zowe/imperative": "8.10.0" + "@zowe/imperative": "8.10.1" }, "peerDependencies": { "@zowe/imperative": "^8.0.0" diff --git a/lerna.json b/lerna.json index 20d40cb3b5..1df9859d41 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "8.10.0", + "version": "8.10.1", "command": { "publish": { "ignoreChanges": [ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 486f42b2ad..62f8db5971 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -52,7 +52,7 @@ }, "__tests__/__packages__/cli-test-utils": { "name": "@zowe/cli-test-utils", - "version": "8.10.0", + "version": "8.10.1", "license": "EPL-2.0", "dependencies": { "find-up": "^5.0.0", @@ -63,7 +63,7 @@ "devDependencies": { "@types/js-yaml": "^4.0.9", "@types/uuid": "^10.0.0", - "@zowe/imperative": "8.10.0" + "@zowe/imperative": "8.10.1" }, "peerDependencies": { "@zowe/imperative": "^8.0.0" @@ -16269,21 +16269,21 @@ }, "packages/cli": { "name": "@zowe/cli", - "version": "8.10.0", + "version": "8.10.1", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0", - "@zowe/provisioning-for-zowe-sdk": "8.10.0", - "@zowe/zos-console-for-zowe-sdk": "8.10.0", - "@zowe/zos-files-for-zowe-sdk": "8.10.0", - "@zowe/zos-jobs-for-zowe-sdk": "8.10.0", - "@zowe/zos-logs-for-zowe-sdk": "8.10.0", - "@zowe/zos-tso-for-zowe-sdk": "8.10.0", - "@zowe/zos-uss-for-zowe-sdk": "8.10.0", - "@zowe/zos-workflows-for-zowe-sdk": "8.10.0", - "@zowe/zosmf-for-zowe-sdk": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1", + "@zowe/provisioning-for-zowe-sdk": "8.10.1", + "@zowe/zos-console-for-zowe-sdk": "8.10.1", + "@zowe/zos-files-for-zowe-sdk": "8.10.1", + "@zowe/zos-jobs-for-zowe-sdk": "8.10.1", + "@zowe/zos-logs-for-zowe-sdk": "8.10.1", + "@zowe/zos-tso-for-zowe-sdk": "8.10.1", + "@zowe/zos-uss-for-zowe-sdk": "8.10.1", + "@zowe/zos-workflows-for-zowe-sdk": "8.10.1", + "@zowe/zosmf-for-zowe-sdk": "8.10.1", "find-process": "1.4.7", "lodash": "4.17.21", "minimatch": "9.0.5", @@ -16296,7 +16296,7 @@ "@types/diff": "^5.0.9", "@types/lodash": "^4.17.6", "@types/tar": "^6.1.11", - "@zowe/cli-test-utils": "8.10.0", + "@zowe/cli-test-utils": "8.10.1", "comment-json": "^4.2.3", "strip-ansi": "^6.0.1", "which": "^4.0.0" @@ -16352,15 +16352,15 @@ }, "packages/core": { "name": "@zowe/core-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "license": "EPL-2.0", "dependencies": { "comment-json": "~4.2.3", "string-width": "^4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/imperative": "8.10.1" }, "engines": { "node": ">=18.12.0" @@ -16371,7 +16371,7 @@ }, "packages/imperative": { "name": "@zowe/imperative", - "version": "8.10.0", + "version": "8.10.1", "license": "EPL-2.0", "dependencies": { "@types/yargs": "^17.0.32", @@ -16565,16 +16565,16 @@ }, "packages/provisioning": { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "license": "EPL-2.0", "dependencies": { "js-yaml": "^4.1.0" }, "devDependencies": { "@types/js-yaml": "^4.0.9", - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "engines": { "node": ">=18.12.0" @@ -16599,15 +16599,15 @@ }, "packages/workflows": { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.10.0" + "@zowe/zos-files-for-zowe-sdk": "8.10.1" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "engines": { "node": ">=18.12.0" @@ -16619,12 +16619,12 @@ }, "packages/zosconsole": { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "engines": { "node": ">=18.12.0" @@ -16636,17 +16636,17 @@ }, "packages/zosfiles": { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "license": "EPL-2.0", "dependencies": { "lodash": "^4.17.21", "minimatch": "^9.0.5" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0", - "@zowe/zos-uss-for-zowe-sdk": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1", + "@zowe/zos-uss-for-zowe-sdk": "8.10.1" }, "engines": { "node": ">=18.12.0" @@ -16678,15 +16678,15 @@ }, "packages/zosjobs": { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.10.0" + "@zowe/zos-files-for-zowe-sdk": "8.10.1" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "engines": { "node": ">=18.12.0" @@ -16698,12 +16698,12 @@ }, "packages/zoslogs": { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "engines": { "node": ">=18.12.0" @@ -16715,12 +16715,12 @@ }, "packages/zosmf": { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "engines": { "node": ">=18.12.0" @@ -16732,15 +16732,15 @@ }, "packages/zostso": { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "license": "EPL-2.0", "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "8.10.0" + "@zowe/zosmf-for-zowe-sdk": "8.10.1" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "engines": { "node": ">=18.12.0" @@ -16752,15 +16752,15 @@ }, "packages/zosuss": { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "license": "EPL-2.0", "dependencies": { "ssh2": "^1.15.0" }, "devDependencies": { "@types/ssh2": "^1.11.19", - "@zowe/cli-test-utils": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/imperative": "8.10.1" }, "engines": { "node": ">=18.12.0" diff --git a/packages/cli/package.json b/packages/cli/package.json index 6f4a7fec69..cf52e04915 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli", - "version": "8.10.0", + "version": "8.10.1", "zoweVersion": "v3.0.0", "description": "Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.", "author": "Zowe", @@ -58,17 +58,17 @@ "preshrinkwrap": "node ../../scripts/rewriteShrinkwrap.js" }, "dependencies": { - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0", - "@zowe/provisioning-for-zowe-sdk": "8.10.0", - "@zowe/zos-console-for-zowe-sdk": "8.10.0", - "@zowe/zos-files-for-zowe-sdk": "8.10.0", - "@zowe/zos-jobs-for-zowe-sdk": "8.10.0", - "@zowe/zos-logs-for-zowe-sdk": "8.10.0", - "@zowe/zos-tso-for-zowe-sdk": "8.10.0", - "@zowe/zos-uss-for-zowe-sdk": "8.10.0", - "@zowe/zos-workflows-for-zowe-sdk": "8.10.0", - "@zowe/zosmf-for-zowe-sdk": "8.10.0", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1", + "@zowe/provisioning-for-zowe-sdk": "8.10.1", + "@zowe/zos-console-for-zowe-sdk": "8.10.1", + "@zowe/zos-files-for-zowe-sdk": "8.10.1", + "@zowe/zos-jobs-for-zowe-sdk": "8.10.1", + "@zowe/zos-logs-for-zowe-sdk": "8.10.1", + "@zowe/zos-tso-for-zowe-sdk": "8.10.1", + "@zowe/zos-uss-for-zowe-sdk": "8.10.1", + "@zowe/zos-workflows-for-zowe-sdk": "8.10.1", + "@zowe/zosmf-for-zowe-sdk": "8.10.1", "find-process": "1.4.7", "lodash": "4.17.21", "minimatch": "9.0.5", @@ -78,7 +78,7 @@ "@types/diff": "^5.0.9", "@types/lodash": "^4.17.6", "@types/tar": "^6.1.11", - "@zowe/cli-test-utils": "8.10.0", + "@zowe/cli-test-utils": "8.10.1", "comment-json": "^4.2.3", "strip-ansi": "^6.0.1", "which": "^4.0.0" diff --git a/packages/core/package.json b/packages/core/package.json index bd4db2f727..91a8be1c76 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/core-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "description": "Core libraries shared by Zowe SDK packages", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ "string-width": "^4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/imperative": "8.10.1" }, "peerDependencies": { "@zowe/imperative": "^8.0.0" diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index 31d5b27ac3..0ba57c37bf 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to the Imperative package will be documented in this file. -## Recent Changes +## `8.10.1` - BugFix: Resolved an issue where base profiles in a team configuration file were overwritten when a user configuration file did not include a base profile. [#2383](https://github.com/zowe/zowe-cli/pull/2383) diff --git a/packages/imperative/package.json b/packages/imperative/package.json index addb75bd41..1f79f56d67 100644 --- a/packages/imperative/package.json +++ b/packages/imperative/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/imperative", - "version": "8.10.0", + "version": "8.10.1", "description": "framework for building configurable CLIs", "author": "Zowe", "license": "EPL-2.0", diff --git a/packages/provisioning/package.json b/packages/provisioning/package.json index 2453327ebf..d73cca706d 100644 --- a/packages/provisioning/package.json +++ b/packages/provisioning/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "description": "Zowe SDK to interact with the z/OS provisioning APIs", "author": "Zowe", "license": "EPL-2.0", @@ -49,9 +49,9 @@ }, "devDependencies": { "@types/js-yaml": "^4.0.9", - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/workflows/package.json b/packages/workflows/package.json index 696c7bf8b8..83e62ab6ef 100644 --- a/packages/workflows/package.json +++ b/packages/workflows/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "description": "Zowe SDK to interact with the z/OS workflows APIs", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.10.0" + "@zowe/zos-files-for-zowe-sdk": "8.10.1" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zosconsole/package.json b/packages/zosconsole/package.json index 1f0e7d4dad..a8bb679910 100644 --- a/packages/zosconsole/package.json +++ b/packages/zosconsole/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "description": "Zowe SDK to interact with the z/OS console", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zosfiles/package.json b/packages/zosfiles/package.json index 27302db5f8..a3d961cdec 100644 --- a/packages/zosfiles/package.json +++ b/packages/zosfiles/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "description": "Zowe SDK to interact with files and data sets on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -50,10 +50,10 @@ "minimatch": "^9.0.5" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0", - "@zowe/zos-uss-for-zowe-sdk": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1", + "@zowe/zos-uss-for-zowe-sdk": "8.10.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zosjobs/package.json b/packages/zosjobs/package.json index d403fdb683..cdd98b4ab8 100644 --- a/packages/zosjobs/package.json +++ b/packages/zosjobs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "description": "Zowe SDK to interact with jobs on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -46,12 +46,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.10.0" + "@zowe/zos-files-for-zowe-sdk": "8.10.1" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zoslogs/package.json b/packages/zoslogs/package.json index 4d5cce70e9..df452cd7ca 100644 --- a/packages/zoslogs/package.json +++ b/packages/zoslogs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "description": "Zowe SDK to interact with the z/OS logs", "author": "Zowe", "license": "EPL-2.0", @@ -45,9 +45,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zosmf/package.json b/packages/zosmf/package.json index fa09136aa6..e25ea44139 100644 --- a/packages/zosmf/package.json +++ b/packages/zosmf/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "description": "Zowe SDK to interact with the z/OS Management Facility", "author": "Zowe", "license": "EPL-2.0", @@ -44,9 +44,9 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zostso/package.json b/packages/zostso/package.json index 41a72be750..e9bb16f105 100644 --- a/packages/zostso/package.json +++ b/packages/zostso/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "description": "Zowe SDK to interact with TSO on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,12 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "8.10.0" + "@zowe/zosmf-for-zowe-sdk": "8.10.1" }, "devDependencies": { - "@zowe/cli-test-utils": "8.10.0", - "@zowe/core-for-zowe-sdk": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/core-for-zowe-sdk": "8.10.1", + "@zowe/imperative": "8.10.1" }, "peerDependencies": { "@zowe/core-for-zowe-sdk": "^8.0.0", diff --git a/packages/zosuss/package.json b/packages/zosuss/package.json index 60e7ffbd0a..2b5821dfe7 100644 --- a/packages/zosuss/package.json +++ b/packages/zosuss/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "8.10.0", + "version": "8.10.1", "description": "Zowe SDK to interact with USS on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -49,8 +49,8 @@ }, "devDependencies": { "@types/ssh2": "^1.11.19", - "@zowe/cli-test-utils": "8.10.0", - "@zowe/imperative": "8.10.0" + "@zowe/cli-test-utils": "8.10.1", + "@zowe/imperative": "8.10.1" }, "peerDependencies": { "@zowe/imperative": "^8.0.0" From d108662e4b0c62e488b81bb2e156cc9b9c6eb0ab Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Wed, 18 Dec 2024 13:21:35 -0500 Subject: [PATCH 61/61] Add new 'Edge Case' section Signed-off-by: Gene Johnston --- docs/Design_for_selecting_auth_type.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/Design_for_selecting_auth_type.md b/docs/Design_for_selecting_auth_type.md index 9466b16a2d..c7f2c9761a 100644 --- a/docs/Design_for_selecting_auth_type.md +++ b/docs/Design_for_selecting_auth_type.md @@ -157,9 +157,21 @@ That addition would enable customers to also specify the authentication order of - We must notify extenders to guide their customers to supply an appropriate authOrder property if their extension needs a non-default order. +## Edge cases that must be confirmed during implementation + +Every edge case was not included in the protype used to confirm the validity of this design document. The following edge cases must be confirmed and appropriate logic must be written during the implementation of this design. + +- As an alternative to user & password, a property named base64EncodedAuth can be used in a session. The new APIs must handle this alternative. + +- To login to APIML, a user supplies a user & password (or cert) and receives a token. The new APIs must determine the correct authentication type for such a session which kind of morphs its authentication type during the transaction. + +- Zowe Explorer currently inherits the same hard-coded order as the CLI from the client SDKs. The new authentication order APIs must be integrated into the APIs used by Zowe Explorer. We must confirm whether any additional logic changes must be made within Zowe Explorer itself. + +- TSO commands can create a sequence of actions, which use a user & password, receive a token from TSO, and then use that token for additional actions. This change in authentication type during the life of a single transaction may be self contained within the transaction and may not not influenced by either the existing hard-coded authentication order or the new user-controlled authentication order. This behavior must be confirmed and modifications made if necessary. + ## A new class must be created to support authOrder -A new class located in +A new class located in:     [zowe-cli/packages/imperative/src/rest/src/session/AuthOrder.ts](https://github.com/zowe/zowe-cli/blob/master/packages/imperative/src/rest/src/session/AuthOrder.ts)