Using tokens in the Zowe CLI

Gene Johnston
Zowe
Published in
15 min readJun 10, 2020
Photo by ZSun Fu on Unsplash

Introduction

{Core} Gregory MacKinnon’s article titled “Zowe API Security — securing the open mainframe” and Dan Kelosky’s article titled “Zowe CLI: Token Authentication, MFA, and SSO” provide an important foundational understanding of security concepts that lead to Zowe CLI’s use of tokens to authenticate a user. In this article I describe the reasons why token handling is important for the Open Mainframe Project’s Zowe CLI, how tokens operate in the CLI, and how consumers configure and use tokens.

In a companion article titled “Token Handling in Zowe CLI plug-ins” I describe how development teams can modify Zowe CLI plug-ins to be compatible with our token technology.

What’s wrong with user name and password?

Until now, the Zowe CLI used a user name and password to authenticate to an underlying service. Many of the core Zowe commands authenticate to the z/OSMF service (which, in turn, calls the z/OS System Authorization Facility or SAF). Plug-ins can authenticate to z/OSMF or to their own back-end server.

Some customer sites do not want user name and password stored on a local workstation’s disk, even if they are encrypted within a secure store. Some sites will add a second factor to the password. The second factor may change every few seconds, so even if it were permissible to store the password on disk, the password would be useless after a few seconds.

GUI applications typically log in once (often with username and password) to establish a session to a back-end service. They retain that session until the user exits the app. A user could interact with such an app for hours without having to login again. A CLI application lives for a very short time. Once the user sees the command prompt again, anything related to authentication and an established session are gone. The next CLI command must start all over again: login, establish a session, do its work, and terminate. If you cannot store the password on disk, or if the password changes every few seconds, a CLI user would be forced to specify a user name and a (potentially changing) password on every command. This makes for an unusable command line application.

Another difficulty is encountered when a user wants to manage the same credentials for multiple services. The user has to manage them separately for each service, thus creating additional work for the user. Even if it is permissible to store user and password on disk, the Zowe CLI and multiple plug-ins may use the same credentials, or they may use different credentials. Zowe CLI profiles enable users to store separate credentials for the services used by the various commands, but profiles do not eliminate duplicated credentials among those profiles nor the need to maintain different sets of credentials for the various commands. This leads to the desire for a single sign-on capability that would enable one set of credentials to access every back-end service to which the Zowe CLI can talk.

While this article focuses on the use of tokens, please note that user name and password can still be used with the Zowe CLI as they have been in the past.

How will tokens help?

The auth0.com website provides a good general description of an authentication token:

A token is a piece of data that has no meaning or use on its own, but combined with the correct tokenization system, becomes a vital player in securing your application. Token based authentication works by ensuring that each request to a server is accompanied by a signed token which the server verifies for authenticity and only then responds to the request.

Tokens can be associated with a physical device like a dongle. They can be generated from a bio-metric device. A token used with Zowe CLI is a software-generated blob of Base64 encoded data that is created by the Zowe API Mediation Layer authentication server. Such a token would look something like this:

OR1EzKCYPXdVCpBeydUXqZOlgflkOAQfzY0ByR8IArRa4c+CuZ/W0TJWnnTJZ8hiyoqBp+f6x1lIHONS+Gjx8kxiktACOv6m2fTE+XOkiV61/vXEctMe/6qOlS0pRKbkORskve4J1z8NlYRbGesfcoBVTUUzwgWchK8xgVyXPvYXEq3F4sWqnbwmBnEy5LWjwB6ZsHkM8NrMaM2nMDi3hvSRtXpv5v1m7zwTKUIeUUHYtOH/IYJkxc3ocvpG9IqRVul0+uQVcjZ8c0rdq0PpSz1F79KFTD6N/d2KSEaBoLeDADufVJOv/YGWpr57F0jc

A token is generated in response to a login request which contains a user name and password. After an app receives a token, all future service requests contain the token. The user name and password are no longer required.

In a customer site where passwords may not be stored on disk, it might be permissible to store a token on disk. A token should still be treated as secret data. However, someone who casually observes a token displayed on screen will be unable to memorize the token, like one could a password. Since a token can be revoked without disabling the user’s password; and a user can login to obtain a new token, exposure from a compromised token can be easily remediated. Also, tokens are frequently configured to expire within hours, so exposure is more limited. For these reasons, a site may allow tokens to be stored on disk.

The default token-handling behavior of Zowe CLI is to store a token within a Zowe CLI profile. If the workstation is using the Zowe secure credential store, the token will live in the platform’s secure credential store, and the Zowe CLI profile will indicate that is where the token has been stored.

Sites that use a second factor with the password, where the second-factor changes every few seconds, can use the login command with the user name and the augmented password to obtain a token. Tokens typically last for hours before they expire. So, numerous Zowe commands can be run without requiring the user to specify any credentials because Zowe automatically uses the stored token. When a token does expire, a Zowe command will fail with an ‘expired token’ error. The user can log in again to obtain a new token and the entire cycle starts over again. It is quite feasible for a user to login in the morning and continues the rest of the workday without explicitly specifying credentials again.

If a site does not permit tokens to be stored on a workstation’s hard drive (perhaps the user must keep the token on a thumb drive), options in the Zowe CLI can be specified to display the token, but not store the token to disk. It then becomes the user’s responsibility to place the token into a file on the thumb drive. In such a situation, the user would also have to specify the token on each Zowe command (or place the token in an environment variable). This may be rather cumbersome, but extra effort is frequently required in sites that enforce higher levels of security.

The ability to generate a token, display it, and not store it would also be used to create a token for use in continuous integration pipelines. The user would not want the token to be stored on the user’s workstation. Instead, the user would copy the token into a pipeline script on a continuous integration server. Pipelines could then be run until the token expires.

API Mediation Layer authentication

To use tokens, a customer site must install and configure the Zowe API Mediation layer. Zowe CLI’s token handling relies on the APIML authentication server. A login request (with user name and password) is made to APIML. The APIML server authenticates the user and generates a token that represents that user. The token is returned in the APIML response. The CLI stores the token and supplies that token to APIML for authentication of future commands.

As a result, when using tokens, all Zowe CLI REST commands must be routed through the API Mediation Layer. The ability for Zowe CLI to route REST requests to APIML has existed for some time, and documentation exists to configure such an environment. Here is a brief summary of the Zowe CLI’s newly augmented APIML configuration process.

  • You specify the APIML host and port within a new base profile (more on base profiles later). An authentication token is also stored in your base profile.
  • Within the profile for your specific service, you identify a basePath to be used to access that service through APIML. The basePath is the base of the URL path that must be used to make a REST request of the desired service through APIML. For example, users typically have a zosmf profile. To access z/OSMF services through APIML, one adds a basePath property to the zosmf profile. A basePath value for zosmf could be similar to the following text. The specific value could vary based on how your site has configured APIML.
     basePath: api/v1

Every different REST service will have a different basePath value for that service.

With such a configuration, a CLI command uses properties from the base profile to connect to the APIML. It uses the token to authenticate the user through APIML. It uses the basePath from the service profile to form the URL that will enable APIML to route the request to the desired service.

While user name and password can still be used with APIML, the token-handling capabilities of Zowe CLI and APIML will enable sites to use tokens (instead of user name and password) on Zowe CLI requests to mainframe services, other than the login request itself.

API Mediation Layer single sign-on

Token handling provides the Zowe API Mediation Layer the building block for single sign-on. Assume that a plug-in’s service is configured to route through APIML as described above. If a token is supplied to the plug-in’s commands, APIML will perform single sign-on.

After a user logs into the Zowe-CLI, the resulting token can be supplied on requests to any service which participates in the APIML single sign-on mechanism. APIML passes the token, along with the request, to the desired back-end service. Because the back-end services accept the token as proof that the user has properly authenticated, the user is not required to log in again to any of the back-end services. This relationship among the various components is shown in the diagram below.

Single sign-on with APIML

A customer site must know which plug-in services have been modified to participate in the APIML single sign-on mechanism and which services have not. To achieve single sign-on functionality, a site must supply a token to any plug-in service which supports single sign-on. The site must supply a user name and password to any plug-in service which has not been modified to work with single sign-on. APIML will not attempt to perform single sign-on when a user name and password is specified.

Since each service must be modified to participate in APIML’s single sign-on mechanism, the number of such services will gradually increase. When the first SSO functionality is rolled out, the services that we expect will be accessible through SSO are z/OSMF and Endevor.

New base profile

I referred to a base profile earlier in the context of connecting to APIML. For our focus on tokens, that is a valid context. However, to understand how you configure your site for different scenarios, you must understand the role of a base profile. A base profile is a potential source of options for Zowe CLI commands. Let me summarize the sources of options and their order of precedence for overriding an option’s value.

  1. An option specified on the command line will override an identical option specified anywhere else.
  2. If an option is not present on the command line, Zowe CLI will then look for Environment variables (with a documented naming convention). An environment variable will override an identical option specified by any of the means below.
  3. If an option is not specified by any of the means above, the Zowe CLI will then look for an option in a service profile. This was the only type of profile that previously existed in Zowe CLI (we previously just called them profiles). Examples of service profiles include zosmf, Endevor, CICS, DB2, etc. A value in a service profile will override an identical option specified by any of the means below.
  4. If a select set of options are not specified by any of the means above, the Zowe CLI will then look for such an option in a base profile. This is new. The reason that we created a base profile was to address a need to place some options, which apply to every service, in one place.

The following options can be stored in a base profile:

  • host
  • port
  • user
  • password
  • rejectUnauthorized
  • tokenType
  • tokenValue

For example, if you have a mainframe user name and password that gives you access to every service at your site, it is much easier to maintain the user name and password in your one base profile, rather than duplicating the user name and password in every one of your service profiles. You might choose to take advantage of this feature, even if you do not intend to use tokens, single sign-on, or APIML.

A base profile is tailor-made for use with APIML and tokens. When using APIML, the hostname and port number are those for APIML, regardless of which underlying service will actually process your request. Also, when the Zowe CLI logs into APIML to get a token, it receives a token that APIML uses to authenticate future requests. The token only needs to be stored in one place (the base profile) regardless of which service is targeted by such future commands.

Base profile scenarios

You can have multiple base profiles and a selected default base profile. This is just like having multiple zosmf profiles. For example, you might have one base profile related to your personal user name and another base profile related to a QA-test user name. Another example might be if you had one base profile for your production instance of APIML, and another base profile for your test instance of APIML.

Remember your order of precedence. Let’s assume that you have existing service profiles containing user name and password and you decide that you want the base profile to be the sole source of user name and password. Once you create the base profile, the order of precedence will override the base profile’s user name and password with the individual service profile’s values. You will have to recreate your service profiles without user name and password.

Let’s assume that you have existing service profiles containing user name and password and you decide that you want to use tokens. You log in and a token is automatically stored in a base profile. When you run your next command, both user name & password and a token will be available as options to that command. The Zowe CLI will choose to use user name & password in lieu of a token. Again, you will have to recreate the service profiles without user name & password if you want to use tokens. This seems reasonable since the premise of a customer site that wants to use tokens is that they do not want the user name & password stored on disk, or they change too often to be useful. We feel that most sites will either go all-in on tokens or that they remain satisfied with user name & password. They are unlikely to want a mix of both.

A site that is interested in tokens as a means to use APIML’s single sign-on, might actually want the mix of user name & password and tokens described in the previous paragraph, at least temporarily. As long as single sign-on has a limited set of participating services, a site might log in to create a token that can be used for single sign-on with the initial services of z/OSMF and Endevor. Of course, the token will reside in a base profile. The service profiles for zosmf and Endevor must contain no user name or password. Another service that has not yet re-tooled to work with APIML’s single sign-on could keep a user name and password in its service profile. Zowe CLI’s choice to use user name & password when they are available over any existing token would enable z/OSMF and Endevor to use the token for single sign-on while the third service continues to use a user name and password (no single sign-on).

As you can see, numerous variations can exist. You must follow the order of precedence to determine how to achieve the outcome needed at your site. Often flexibility comes with the price of some complexity.

Prompting for connection information

Due to our increased focus on credentials within the Zowe CLI, we altered the behavior of commands to prompt for credentials and connection information when they have not been supplied to a command. A REST connection requires a hostname, port number, and credentials (user name & password, or a token). Previously, commands simply reported an error when any of these items were missing. For example, if no user name and password were supplied to a command, a command’s response previously looked like this:

zowe zos-files list data-set “MYUSER.ISPF.*”
Command Error:
Must have user & password OR base64 encoded credentials
Error Details:
For CLI usage, see ‘zowe zosmf login — help’

A new feature for Zowe commands is that they will prompt for the following options when any of the options have not been supplied.

  • host name
  • port number
  • user name
  • password

After prompting for the required information, the command is run as requested. In the following example, only the port number was supplied in a profile.

zowe zos-files list data-set “MYUSER.ISPF.*”
Enter the host name of your service: YourMainframeHostName
Enter user name: myuser
Enter password : ********
MYUSER.ISPF.ISPPROF

Note that when a token is supplied, no user name and password are required. If no user name, password, or token is supplied, you are prompted for a user name and password.

Because Zowe commands are intended to run within scripts and continuous integration pipelines, it is very important that a command does not wait indefinitely, as would happen if the command were to wait for a response to an interactive prompt within a CI pipeline. Therefore, any prompt will automatically time-out after 30 seconds. Thirty seconds seems like adequate time for a real user to respond and is small enough that it will have insignificant impact on an automated pipeline. An example of the same command when it times-out is shown below.

zowe zos-files list data-set “MYUSER.ISPF.*”
Enter the host name of your service: Command Error:
We timed-out waiting for host name.

Connection information obtained through prompts is only used once. The next Zowe command will prompt the user for the information again. Such behavior is impractical for running many commands in sequence. However, for a one-off command, it could be convenient. For a new user learning about Zowe commands for the first time, it certainly informs the user that certain connection information is required. The intent is that a new user will learn that the inconvenience of typing connection information for every command can be overcome through the use of profiles.

The most valuable use of prompting for connection information occurs when running the new Zowe login command.

New Zowe login command

The new Zowe login command enables a user to authenticate once with a user name and password. Afterward, the user will not be required to supply a user name and password for other Zowe commands.

The way that the login command eliminates the need for a user name and password on every command is by obtaining and storing a token that represents that authenticated user. Other Zowe commands use the token so that they do not require a user name and password.

Before issuing a login command, the best practice is to create a base profile specifying the host and port of the APIML server that will perform the authentication of the login. If you do not create such a profile, you will be prompted for that connection information.

The components of the login command represent an authentication group, a login command, and the API Mediation Layer as the authentication service.

zowe auth login apiml

It is somewhat inconvenient for the user to specify a user name and password on the login command line (although that is possible). As a result, the login command is an ideal candidate to prompt for credentials, as shown below.

zowe auth login apiml
Enter user name: myuser
Enter password : ********
Login successful.

If you do not create a base profile before running the login command, the login will prompt you for a host name (which must be the host of your APIML service), the port number for that host, your user name, and your password. The login command will then ask if it can automatically create a default base profile into which it will store the host, port, and token. Your user name and password are not stored.

Whether you created a base profile yourself, or let the login command automatically create it, the login command stores the token in your base profile. That token will then be used by other Zowe commands for authentication. At that point, user name and password will not be needed by other Zowe commands. Customer sites that want to eliminate the storage of username and password on workstation hard drives can remove them from all core Zowe profiles and from the profiles of plug-ins that have been modified to use tokens.

New Zowe logout command

The logout command makes a request of the API Mediation Layer authentication service to expire a token. If the token is stored in the base profile, the token is removed from the base profile.

The logout command has the following format:

zowe auth logout apiml

When other Zowe commands are then run, they will not have a token available. They will begin to prompt for user name and password. A user can obtain another token by running the login command again.

Availability of token functionality

These changes were designed to be backward-compatible. Because of the non-breaking nature of these changes to the Zowe CLI, and Imperative framework, we anticipate releasing the token-handling functionality into both the tags @latest and @zowe-v1-lts in the Node Package Manager (NPM) registry of products. These tags represent the latest development version of the product and the current long-term-support version of the product, respectively, for both the Zowe CLI and the Imperative framework.

Zowe is owned and managed by the Open Mainframe Project that is a Linux Foundation project.

Click the links to learn more about Zowe and more Zowe blogs.

--

--

Gene Johnston
Zowe
Writer for

I am a principal software engineer at Broadcom and a contributor to the Command Line Interface component of the Zowe project.