Skip to content

Commit

Permalink
Revert "vdk-control-cli: autodetect if authentication is needed (#305)"
Browse files Browse the repository at this point in the history
This reverts commit ecf0aaf.
  • Loading branch information
antoniivanov authored Sep 30, 2021
1 parent ecf0aaf commit fb0fdb6
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 81 deletions.
2 changes: 0 additions & 2 deletions projects/vdk-control-cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ VDK Control CLI 1.1
Introduced vdk create --local to create job only locally from sample
vdk create without arguments would create job locally and try to detect if it can created in cloud
vdk create --cloud - always created in cloud only and fail if it cannot
* Auto-detect if authentication is necessary
This remove the need of explicit variable to set/unset authentication. Now vdkcli would detect automatically.

* **Bug Fixes**

Expand Down
17 changes: 6 additions & 11 deletions projects/vdk-control-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,15 @@ use `vdkcli` command instead of `vdk`.

### Environment variables:

* VDK_BASE_CONFIG_FOLDER - Override local base configuration folder (by default in $HOME folder). Inside it will create folder .vdk.internal.
CLI state may be kept there (login info). Use in case multiple users need to login (e.g in case of automation) on same machine.

* VDK_CONTROL_SERVICE_REST_API_URL - Default Control Service URL to use if not specified as command line argument
* VDK_API_TOKEN - Default API Token to use if another authentication has not been used with vdk login
* VDK_API_TOKEN_AUTHORIZATION_URL - Default API token URL to use if another authentication has not been used with vdk login.
* VDK_AUTHENTICATION_DISABLE - disables security (vdk login will not be required). See Security section.
* VDK_BASE_CONFIG_FOLDER - Override local base configuration folder (by default $HOME folder) . Use in case multiple users need to login (e.g in case of automation) on same machine.

### Security
If Control Service configured require authentication: vdk login must have finished successfully.
Or alternatively correct VDK_API_TOKEN_AUTHORIZATION_URL and VDK_API_TOKEN must be set correctly and will behave same as `vdk login -t api-token`.
If vdk login is used - it take priority over environment variables set VDK_API_TOKEN_AUTHORIZATION_URL and VDK_API_TOKEN
To clear previous login info (aka logout) use `vdk logout`.
By default, all operation require authentication: vdk login must have finished successfully.
You can disable it with environment variable `VDK_AUTHENTICATION_DISABLE=true`
This would only work if Control Service which VDK CLI uses also has security disabled.

In case of credentials type vdk login flow we start a process on port `31113` to receive the credentials.
In case of credentials type login flow we start a process on port `31113` to receive the credentials.
If you already have process running on `31113` you can override the value.
To override the port set environmental variable `OAUTH_PORT` with free port which the client can use.

Expand Down

This file was deleted.

26 changes: 8 additions & 18 deletions projects/vdk-control-cli/src/vdk/internal/control/auth/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
import json
import logging
import time
from typing import Optional

from requests import post
from requests.auth import HTTPBasicAuth
from requests_oauthlib import OAuth2Session
from vdk.internal.control.auth.auth_request_values import AuthRequestValues
from vdk.internal.control.auth.login_types import LoginTypes
from vdk.internal.control.configuration.vdk_config import VDKConfig
from vdk.internal.control.configuration.vdk_config import VDKConfigFolder
from vdk.internal.control.exception.vdk_exception import VDKException

Expand Down Expand Up @@ -84,9 +82,8 @@ def deserialize(content: str):
class Authentication:
REFRESH_TOKEN_GRANT_TYPE = "refresh_token" # nosec

def __init__(self, conf=VDKConfigFolder(), vdk_config=VDKConfig()):
def __init__(self, conf=VDKConfigFolder()):
self._conf = conf
self.__vdk_config = vdk_config
self._cache = self.__load_cache()

def __load_cache(self):
Expand Down Expand Up @@ -132,12 +129,12 @@ def __exchange_api_for_access_token(self):
+ int(token_response.get(AuthRequestValues.EXPIRATION_TIME_KEY.value, "0"))
)

def read_access_token(self) -> Optional[str]:
def read_access_token(self):
"""
Read access token from _cache or fetch it from Authorization server.
If not available in _cache it will get it using provided configuration during VDK CLI login to fetch it.
If it detects that token is about to expire it will try to refresh it.
:return: the access token or None if it cannot detect any credentials.
:return: the access token
"""
if (
not self._cache.access_token
Expand All @@ -162,19 +159,12 @@ def acquire_and_cache_access_token(self):
and self._configured_refresh_token()
):
self.__exchange_refresh_for_access_token()
elif (
self.__vdk_config.api_token
and self.__vdk_config.api_token_authorization_url
):
self.update_api_token(self.__vdk_config.api_token)
self.update_api_token_authorization_url(
self.__vdk_config.api_token_authorization_url
)
self.__exchange_api_for_access_token()
else:
log.debug(
"No authentication mechanism found. Will not cache access token."
"If Control Service authentication is enabled, API calls will fail."
raise VDKException(
what="Not authenticated.",
why="Most likely VDK CLI login need to be completed first.",
consequence="Operation that require authorization will not work.",
countermeasure="Please execute login using VDK CLI login command",
)

def __exchange_refresh_for_access_token(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
# Copyright 2021 VMware, Inc.
# SPDX-License-Identifier: Apache-2.0
import click
from vdk.internal.control.auth.apikey_auth import ApiKeyAuthentication
from vdk.internal.control.auth.auth import Authentication
from vdk.internal.control.auth.login_types import LoginTypes
from vdk.internal.control.auth.redirect_auth import RedirectAuthentication
from vdk.internal.control.configuration.vdk_config import VDKConfig
from vdk.internal.control.exception.vdk_exception import VDKException
from vdk.internal.control.utils import cli_utils
from vdk.internal.control.utils.cli_utils import extended_option
Expand Down Expand Up @@ -133,8 +131,11 @@ def login(
countermeasure="Please login providing correct API Token. ",
)
else:
apikey_auth = ApiKeyAuthentication(api_token_authorization_url, api_token)
apikey_auth.authentication_process()
auth = Authentication()
auth.update_api_token_authorization_url(api_token_authorization_url)
auth.update_api_token(api_token)
auth.update_auth_type(auth_type)
auth.acquire_and_cache_access_token()
click.echo("Login Successful")
else:
click.echo(f"Login type: {auth_type} not supported")
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,25 @@ def local_config_folder(self) -> str:
"""
return os.getenv("VDK_BASE_CONFIG_FOLDER", str(Path.home()))

@property
def authentication_disabled(self) -> bool:
return os.getenv("VDK_AUTHENTICATION_DISABLE", "False").lower() in (
"true",
"1",
"t",
)

@property
def control_service_rest_api_url(self) -> str:
return os.getenv("VDK_CONTROL_SERVICE_REST_API_URL", None)

@property
def api_token_authorization_url(self) -> str:
def api_token_authorization_server_url(self) -> str:
"""
Location of the API Token OAuth2 provider. Same as login --api-token-authorization-server-url
This is used as default.
"""
return os.getenv("VDK_API_TOKEN_AUTHORIZATION_URL", None)
return os.getenv("VDK_API_TOKEN_AUTHORIZATION_SERVER_URL", None)

@property
def api_token(self) -> str:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,16 @@ def __init__(self, rest_api_url):
)
self.config.client_side_validation = False
self.config.verify_ssl = self.vdk_config.http_verify_ssl

auth = Authentication()
# For now there's no need to add auto-update since this is called usually in a shell script
# and each command will have short execution life even when multiple requests to API are made.
self.config.access_token = auth.read_access_token()
if (
self.vdk_config.authentication_disabled
or load_default_authentication_disable()
):
log.info("Authentication is disabled.")
else:
auth = Authentication()
# For now there's no need to add auto-update since this is called usually in a shell script
# and each command will have short execution life even when multiple requests to API are made.
self.config.access_token = auth.read_access_token()

def _new_api_client(self):
api_client = ApiClient(self.config)
Expand Down

0 comments on commit fb0fdb6

Please sign in to comment.