-
-
Notifications
You must be signed in to change notification settings - Fork 782
Adding support for st2 login and st2 whoami commands
#3123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ddb85ff
7c97cb5
a8f4f36
67a18aa
2d31ff1
03fb3f6
66fd541
eb3aedc
a050a9f
683cb4d
7b9dcb6
47529e0
9ae4d07
dafb4e1
2a4d38d
9ca6a40
ec480ff
05a4987
d45b9af
51de077
7a2ce39
079c89b
8f68d55
5f87719
3f2c565
da93e1b
3da2b42
369978e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,10 +13,13 @@ | |
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| from configparser import ConfigParser | ||
| import getpass | ||
| import json | ||
| import logging | ||
|
|
||
| from st2client.base import BaseCLIApp | ||
| from st2client import config_parser | ||
| from st2client import models | ||
| from st2client.commands import resource | ||
| from st2client.commands.noop import NoopCommand | ||
|
|
@@ -37,7 +40,7 @@ def __init__(self, resource, *args, **kwargs): | |
|
|
||
| super(TokenCreateCommand, self).__init__( | ||
| resource, kwargs.pop('name', 'create'), | ||
| 'Authenticate user and aquire access token.', | ||
| 'Authenticate user and acquire access token.', | ||
| *args, **kwargs) | ||
|
|
||
| self.parser.add_argument('username', | ||
|
|
@@ -70,6 +73,124 @@ def run_and_print(self, args, **kwargs): | |
| attributes=self.display_attributes, json=args.json, yaml=args.yaml) | ||
|
|
||
|
|
||
| class LoginCommand(resource.ResourceCommand): | ||
| display_attributes = ['user', 'token', 'expiry'] | ||
|
|
||
| def __init__(self, resource, *args, **kwargs): | ||
|
|
||
| kwargs['has_token_opt'] = False | ||
|
|
||
| super(LoginCommand, self).__init__( | ||
| resource, kwargs.pop('name', 'create'), | ||
| 'Authenticate user, acquire access token, and update CLI config directory', | ||
| *args, **kwargs) | ||
|
|
||
| self.parser.add_argument('username', | ||
| help='Name of the user to authenticate.') | ||
|
|
||
| self.parser.add_argument('-p', '--password', dest='password', | ||
| help='Password for the user. If password is not provided, ' | ||
| 'it will be prompted.') | ||
| self.parser.add_argument('-l', '--ttl', type=int, dest='ttl', default=None, | ||
| help='The life span of the token in seconds. ' | ||
| 'Max TTL configured by the admin supersedes this.') | ||
| self.parser.add_argument('-w', '--write-password', action='store_true', default=False, | ||
| dest='write_password', | ||
| help='Write the password in plain text to the config file ' | ||
| '(default is to omit it') | ||
|
|
||
| def run(self, args, **kwargs): | ||
|
|
||
| if not args.password: | ||
| args.password = getpass.getpass() | ||
| instance = self.resource(ttl=args.ttl) if args.ttl else self.resource() | ||
|
|
||
| cli = BaseCLIApp() | ||
|
|
||
| # Determine path to config file | ||
| try: | ||
| config_file = cli._get_config_file_path(args) | ||
| except ValueError: | ||
| # config file not found in args or in env, defaulting | ||
| config_file = config_parser.ST2_CONFIG_PATH | ||
|
|
||
| # Retrieve token | ||
| manager = self.manager.create(instance, auth=(args.username, args.password), **kwargs) | ||
| cli._cache_auth_token(token_obj=manager) | ||
|
|
||
| # Update existing configuration with new credentials | ||
| config = ConfigParser() | ||
| config.read(config_file) | ||
|
|
||
| # Modify config (and optionally populate with password) | ||
| if 'credentials' not in config: | ||
| config.add_section('credentials') | ||
| config['credentials'] = {} | ||
| config['credentials']['username'] = args.username | ||
| if args.write_password: | ||
| config['credentials']['password'] = args.password | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
| else: | ||
| # Remove any existing password from config | ||
| config['credentials'].pop('password', None) | ||
|
|
||
| with open(config_file, "w") as cfg_file_out: | ||
| config.write(cfg_file_out) | ||
|
|
||
| return manager | ||
|
|
||
| def run_and_print(self, args, **kwargs): | ||
| try: | ||
| self.run(args, **kwargs) | ||
| print("Logged in as %s" % (args.username)) | ||
| except Exception as e: | ||
| print("Failed to log in as %s: %s" % (args.username, str(e))) | ||
| if self.app.client.debug: | ||
| raise | ||
|
|
||
|
|
||
| class WhoamiCommand(resource.ResourceCommand): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to confirm - does this follow the same logic as other commands - aka it takes If not, it would be a good idea to do that otherwise it might be confusing to the user.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To clarify, that are the options I had in mind - https://docs.stackstorm.com/reference/cli.html#configuration-file.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Kami Okay, I tested both the ST2_CONFIG_PATH It should be noted that this tool doesn't actually create the configuration file - as with other commands, if the file doesn't exist at the referenced path, it will raise an exception. I did this to be as predictable compared to other st2 commands as possible. I will push a short note to StackStorm/st2docs#380 to be clear on this |
||
| display_attributes = ['user', 'token', 'expiry'] | ||
|
|
||
| def __init__(self, resource, *args, **kwargs): | ||
|
|
||
| kwargs['has_token_opt'] = False | ||
|
|
||
| super(WhoamiCommand, self).__init__( | ||
| resource, kwargs.pop('name', 'create'), | ||
| 'Display the currently authenticated/configured user', | ||
| *args, **kwargs) | ||
|
|
||
| def run(self, args, **kwargs): | ||
|
|
||
| cli = BaseCLIApp() | ||
|
|
||
| # Determine path to config file | ||
| try: | ||
| config_file = cli._get_config_file_path(args) | ||
| except ValueError: | ||
| # config file not found in args or in env, defaulting | ||
| config_file = config_parser.ST2_CONFIG_PATH | ||
|
|
||
| # Update existing configuration with new credentials | ||
| config = ConfigParser() | ||
| config.read(config_file) | ||
|
|
||
| return config['credentials']['username'] | ||
|
|
||
| def run_and_print(self, args, **kwargs): | ||
| try: | ||
| username = self.run(args, **kwargs) | ||
| print("Currently logged in as %s" % username) | ||
| except KeyError: | ||
| print("No user is currently logged in") | ||
| if self.app.client.debug: | ||
| raise | ||
| except Exception: | ||
| print("Unable to retrieve currently logged-in user") | ||
| if self.app.client.debug: | ||
| raise | ||
|
|
||
|
|
||
| class ApiKeyBranch(resource.ResourceBranch): | ||
|
|
||
| def __init__(self, description, app, subparsers, parent_parser=None): | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scenario: configure .st2/config with
user1with password, rewriting it withst2 login user2, user get rewriten, password remains from user1, token expires, user1 no longer works.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point - so perhaps I can default to deleting the "password" field (or if
--write-passwordis provided, overwrite)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dzimine I took a stab at this in da93e1b - let me know what you think. Seems to work well now for this case