Support adding API keys to client configs
Sets the groundwork for the remainder of #65
This commit is contained in:
		| @@ -24,6 +24,7 @@ import socket | |||||||
| import click | import click | ||||||
| import tempfile | import tempfile | ||||||
| import os | import os | ||||||
|  | import stat | ||||||
| import subprocess | import subprocess | ||||||
| import difflib | import difflib | ||||||
| import re | import re | ||||||
| @@ -63,7 +64,12 @@ def read_from_yaml(cfgfile): | |||||||
|         scheme = 'https' |         scheme = 'https' | ||||||
|     else: |     else: | ||||||
|         scheme = 'http' |         scheme = 'http' | ||||||
|     return host, port, scheme |     if strtobool(api_config['pvc']['api']['authentication']['enabled']): | ||||||
|  |         # Always use the first token | ||||||
|  |         api_key = api_config['pvc']['api']['authentication']['tokens'][0]['token'] | ||||||
|  |     else: | ||||||
|  |         api_key = 'N/A' | ||||||
|  |     return host, port, scheme, api_key | ||||||
|  |  | ||||||
| def get_config(store_data, cluster=None): | def get_config(store_data, cluster=None): | ||||||
|     # This is generally static |     # This is generally static | ||||||
| @@ -79,7 +85,7 @@ def get_config(store_data, cluster=None): | |||||||
|         # This is a reference to an API configuration; grab the details from its listen address |         # This is a reference to an API configuration; grab the details from its listen address | ||||||
|         cfgfile = cluster_details.get('cfgfile') |         cfgfile = cluster_details.get('cfgfile') | ||||||
|         if os.path.isfile(cfgfile): |         if os.path.isfile(cfgfile): | ||||||
|             host, port, scheme = read_from_yaml(cfgfile) |             host, port, scheme, api_key = read_from_yaml(cfgfile) | ||||||
|         else: |         else: | ||||||
|             return { 'badcfg': True } |             return { 'badcfg': True } | ||||||
|     else: |     else: | ||||||
| @@ -87,12 +93,14 @@ def get_config(store_data, cluster=None): | |||||||
|         host = cluster_details['host'] |         host = cluster_details['host'] | ||||||
|         port = cluster_details['port'] |         port = cluster_details['port'] | ||||||
|         scheme = cluster_details['scheme'] |         scheme = cluster_details['scheme'] | ||||||
|  |         api_key = cluster_details['api_key'] | ||||||
|  |  | ||||||
|     config = dict() |     config = dict() | ||||||
|     config['debug'] = False |     config['debug'] = False | ||||||
|     config['cluster'] = cluster |     config['cluster'] = cluster | ||||||
|     config['api_host'] = '{}:{}'.format(host, port) |     config['api_host'] = '{}:{}'.format(host, port) | ||||||
|     config['api_scheme'] = scheme |     config['api_scheme'] = scheme | ||||||
|  |     config['api_key'] = api_key | ||||||
|     config['api_prefix'] = prefix |     config['api_prefix'] = prefix | ||||||
|  |  | ||||||
|     return config |     return config | ||||||
| @@ -107,6 +115,8 @@ def update_store(store_path, store_data): | |||||||
|     store_file = '{}/pvc-cli.json'.format(store_path) |     store_file = '{}/pvc-cli.json'.format(store_path) | ||||||
|     with open(store_file, 'w') as fh: |     with open(store_file, 'w') as fh: | ||||||
|         fh.write(json.dumps(store_data, sort_keys=True, indent=4)) |         fh.write(json.dumps(store_data, sort_keys=True, indent=4)) | ||||||
|  |     # Ensure file has 0600 permissions due to API key storage | ||||||
|  |     os.chmod(store_file, 0o600) | ||||||
|  |  | ||||||
| home_dir = os.environ.get('HOME', None) | home_dir = os.environ.get('HOME', None) | ||||||
| if home_dir: | if home_dir: | ||||||
| @@ -158,10 +168,14 @@ def cli_cluster(): | |||||||
|     '-s/-S', '--ssl/--no-ssl', 'ssl', is_flag=True, default=False, show_default=True, |     '-s/-S', '--ssl/--no-ssl', 'ssl', is_flag=True, default=False, show_default=True, | ||||||
|     help='Whether to use SSL or not.' |     help='Whether to use SSL or not.' | ||||||
| ) | ) | ||||||
|  | @click.option( | ||||||
|  |     '-k', '--api-key', 'api_key', required=False, default=None, | ||||||
|  |     help='An API key to authenticate against the cluster.' | ||||||
|  | ) | ||||||
| @click.argument( | @click.argument( | ||||||
|     'name' |     'name' | ||||||
| ) | ) | ||||||
| def cluster_add(address, port, ssl, name): | def cluster_add(address, port, ssl, name, api_key): | ||||||
|     """ |     """ | ||||||
|     Add a new PVC cluster NAME, via its API connection details, to the configuration of the local CLI client. Replaces any existing cluster with this name. |     Add a new PVC cluster NAME, via its API connection details, to the configuration of the local CLI client. Replaces any existing cluster with this name. | ||||||
|     """ |     """ | ||||||
| @@ -176,7 +190,8 @@ def cluster_add(address, port, ssl, name): | |||||||
|     existing_config[name] = { |     existing_config[name] = { | ||||||
|         'host': address, |         'host': address, | ||||||
|         'port': port, |         'port': port, | ||||||
|         'scheme': scheme |         'scheme': scheme, | ||||||
|  |         'api_key': api_key | ||||||
|     } |     } | ||||||
|     # Update the store |     # Update the store | ||||||
|     update_store(store_path, existing_config) |     update_store(store_path, existing_config) | ||||||
| @@ -218,7 +233,8 @@ def cluster_list(): | |||||||
|     name_length = 5 |     name_length = 5 | ||||||
|     address_length = 10 |     address_length = 10 | ||||||
|     port_length = 5 |     port_length = 5 | ||||||
|     scheme_length = 5 |     scheme_length = 7 | ||||||
|  |     api_key_length = 8 | ||||||
|  |  | ||||||
|     for cluster in clusters: |     for cluster in clusters: | ||||||
|         cluster_details = clusters[cluster] |         cluster_details = clusters[cluster] | ||||||
| @@ -226,13 +242,16 @@ def cluster_list(): | |||||||
|             # This is a reference to an API configuration; grab the details from its listen address |             # This is a reference to an API configuration; grab the details from its listen address | ||||||
|             cfgfile = cluster_details.get('cfgfile') |             cfgfile = cluster_details.get('cfgfile') | ||||||
|             if os.path.isfile(cfgfile): |             if os.path.isfile(cfgfile): | ||||||
|                 address, port, scheme = read_from_yaml(cfgfile) |                 address, port, scheme, api_key = read_from_yaml(cfgfile) | ||||||
|             else: |             else: | ||||||
|                 address, port, scheme = 'N/A', 'N/A', 'N/A' |                 address, port, scheme, api_key = 'N/A', 'N/A', 'N/A', 'N/A' | ||||||
|         else: |         else: | ||||||
|             address = cluster_details.get('host', 'N/A') |             address = cluster_details.get('host', 'N/A') | ||||||
|             port = cluster_details.get('port', 'N/A') |             port = cluster_details.get('port', 'N/A') | ||||||
|             scheme = cluster_details.get('scheme', 'N/A') |             scheme = cluster_details.get('scheme', 'N/A') | ||||||
|  |             api_key = cluster_details.get('api_key', 'N/A') | ||||||
|  |             if not api_key: | ||||||
|  |                 api_key = 'N/A' | ||||||
|  |  | ||||||
|         _name_length = len(cluster) + 1 |         _name_length = len(cluster) + 1 | ||||||
|         if _name_length > name_length: |         if _name_length > name_length: | ||||||
| @@ -246,12 +265,15 @@ def cluster_list(): | |||||||
|         _scheme_length = len(scheme) + 1 |         _scheme_length = len(scheme) + 1 | ||||||
|         if _scheme_length > scheme_length: |         if _scheme_length > scheme_length: | ||||||
|             scheme_length = _scheme_length |             scheme_length = _scheme_length | ||||||
|  |         _api_key_length = len(api_key) + 1 | ||||||
|  |         if _api_key_length > api_key_length: | ||||||
|  |             api_key_length = _api_key_length | ||||||
|  |  | ||||||
|     # Display the data nicely |     # Display the data nicely | ||||||
|     click.echo("Available clusters:") |     click.echo("Available clusters:") | ||||||
|     click.echo() |     click.echo() | ||||||
|     click.echo( |     click.echo( | ||||||
|         '{bold}{name: <{name_length}} {address: <{address_length}} {port: <{port_length}} {scheme: <{scheme_length}}{end_bold}'.format( |         '{bold}{name: <{name_length}} {address: <{address_length}} {port: <{port_length}} {scheme: <{scheme_length}} {api_key: <{api_key_length}}{end_bold}'.format( | ||||||
|             bold=ansiprint.bold(), |             bold=ansiprint.bold(), | ||||||
|             end_bold=ansiprint.end(), |             end_bold=ansiprint.end(), | ||||||
|             name="Name", |             name="Name", | ||||||
| @@ -261,7 +283,9 @@ def cluster_list(): | |||||||
|             port="Port", |             port="Port", | ||||||
|             port_length=port_length, |             port_length=port_length, | ||||||
|             scheme="Scheme", |             scheme="Scheme", | ||||||
|             scheme_length=scheme_length |             scheme_length=scheme_length, | ||||||
|  |             api_key="API Key", | ||||||
|  |             api_key_length=api_key_length | ||||||
|         ) |         ) | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
| @@ -270,18 +294,22 @@ def cluster_list(): | |||||||
|         if cluster_details.get('cfgfile', None): |         if cluster_details.get('cfgfile', None): | ||||||
|             # This is a reference to an API configuration; grab the details from its listen address |             # This is a reference to an API configuration; grab the details from its listen address | ||||||
|             if os.path.isfile(cfgfile): |             if os.path.isfile(cfgfile): | ||||||
|                 address, port, scheme = read_from_yaml(cfgfile) |                 address, port, scheme, api_key = read_from_yaml(cfgfile) | ||||||
|             else: |             else: | ||||||
|                 address = 'N/A' |                 address = 'N/A' | ||||||
|                 port = 'N/A' |                 port = 'N/A' | ||||||
|                 scheme = 'N/A' |                 scheme = 'N/A' | ||||||
|  |                 api_key = 'N/A' | ||||||
|         else: |         else: | ||||||
|             address = cluster_details.get('host', 'N/A') |             address = cluster_details.get('host', 'N/A') | ||||||
|             port = cluster_details.get('port', 'N/A') |             port = cluster_details.get('port', 'N/A') | ||||||
|             scheme = cluster_details.get('scheme', 'N/A') |             scheme = cluster_details.get('scheme', 'N/A') | ||||||
|  |             api_key = cluster_details.get('api_key', 'N/A') | ||||||
|  |             if not api_key: | ||||||
|  |                 api_key = 'N/A' | ||||||
|  |  | ||||||
|         click.echo( |         click.echo( | ||||||
|             '{bold}{name: <{name_length}} {address: <{address_length}} {port: <{port_length}} {scheme: <{scheme_length}}{end_bold}'.format( |             '{bold}{name: <{name_length}} {address: <{address_length}} {port: <{port_length}} {scheme: <{scheme_length}} {api_key: <{api_key_length}}{end_bold}'.format( | ||||||
|                 bold='', |                 bold='', | ||||||
|                 end_bold='', |                 end_bold='', | ||||||
|                 name=cluster, |                 name=cluster, | ||||||
| @@ -291,7 +319,9 @@ def cluster_list(): | |||||||
|                 port=port, |                 port=port, | ||||||
|                 port_length=port_length, |                 port_length=port_length, | ||||||
|                 scheme=scheme, |                 scheme=scheme, | ||||||
|                 scheme_length=scheme_length |                 scheme_length=scheme_length, | ||||||
|  |                 api_key=api_key, | ||||||
|  |                 api_key_length=api_key_length | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user