http: only request with DC/OS Auth if request is to DC/OS cluster (#893)

This commit is contained in:
tamarrow
2017-02-06 13:35:55 -08:00
committed by GitHub
parent ef568580bf
commit 4d8e6e98fd
6 changed files with 110 additions and 66 deletions

View File

@@ -645,6 +645,15 @@ def update_config(name, value, env=None):
returncode, stdout, _ = exec_command(
['dcos', 'config', 'show', name], env)
# when we change the dcos_url we remove the acs_token
# we need to also restore the token if this occurs
token = None
if name == "core.dcos_url":
returncode, token_val, _ = exec_command(
['dcos', 'config', 'show', "core.dcos_acs_token"], env)
if returncode == 0:
token = token_val.decode('utf-8').strip()
result = None
# config param already exists
if returncode == 0:
@@ -666,6 +675,9 @@ def update_config(name, value, env=None):
else:
exec_command(['dcos', 'config', 'unset', name], env)
if token:
config_set("core.dcos_acs_token", token, env)
@contextlib.contextmanager
def package(package_name, deploy=False, args=[]):

View File

@@ -67,15 +67,14 @@ def test_get_missing_property(env):
def test_dcos_url_without_scheme(env):
old = b'http://dcos.snakeoil.mesosphere.com'
new = b"abc.com"
out = b"[core.dcos_url]: changed from '%b' to 'https://%b'\n" % (old, new)
assert_command(
with update_config("core.dcos_url", None, env):
new = b"abc.com"
out = b"[core.dcos_url]: set to 'https://%b'\n" % (new)
assert_command(
['dcos', 'config', 'set', 'core.dcos_url', new.decode('utf-8')],
returncode=0,
stderr=out,
returncode=0,
env=env)
config_set('core.dcos_url', old.decode('utf-8'), env)
def test_get_top_property(env):
@@ -105,11 +104,10 @@ def test_set_core_email_property():
def test_set_existing_string_property(env):
config_set('core.dcos_url',
'http://dcos.snakeoil.mesosphere.com:5081', env)
_get_value('core.dcos_url',
'http://dcos.snakeoil.mesosphere.com:5081', env)
config_set('core.dcos_url', 'http://dcos.snakeoil.mesosphere.com', env)
new_value = 'http://dcos.snakeoil.mesosphere.com:5081'
with update_config('core.dcos_url', new_value, env):
_get_value('core.dcos_url',
'http://dcos.snakeoil.mesosphere.com:5081', env)
def test_set_existing_boolean_property(env):
@@ -126,33 +124,27 @@ def test_set_existing_number_property(env):
def test_set_change_output(env):
assert_command(
['dcos', 'config', 'set', 'core.dcos_url',
'http://dcos.snakeoil.mesosphere.com:5081'],
stderr=(b"[core.dcos_url]: changed from "
b"'http://dcos.snakeoil.mesosphere.com' to "
b"'http://dcos.snakeoil.mesosphere.com:5081'\n"),
['dcos', 'config', 'set', 'core.timeout', '10'],
stderr=b"[core.timeout]: changed from '5' to '10'\n",
env=env)
config_set('core.dcos_url', 'http://dcos.snakeoil.mesosphere.com', env)
config_set('core.timeout', '5', env)
def test_set_same_output(env):
assert_command(
['dcos', 'config', 'set', 'core.dcos_url',
'http://dcos.snakeoil.mesosphere.com'],
stderr=(b"[core.dcos_url]: already set to "
b"'http://dcos.snakeoil.mesosphere.com'\n"),
['dcos', 'config', 'set', 'core.timeout', '5'],
stderr=b"[core.timeout]: already set to '5'\n",
env=env)
def test_set_new_output(env):
config_unset('core.dcos_url', env)
assert_command(
['dcos', 'config', 'set', 'core.dcos_url',
'http://dcos.snakeoil.mesosphere.com:5081'],
stderr=(b"[core.dcos_url]: set to "
b"'http://dcos.snakeoil.mesosphere.com:5081'\n"),
env=env)
config_set('core.dcos_url', 'http://dcos.snakeoil.mesosphere.com', env)
with update_config("core.dcos_url", None, env):
assert_command(
['dcos', 'config', 'set', 'core.dcos_url',
'http://dcos.snakeoil.mesosphere.com:5081'],
stderr=(b"[core.dcos_url]: set to "
b"'http://dcos.snakeoil.mesosphere.com:5081'\n"),
env=env)
def test_set_nonexistent_subcommand(env):
@@ -175,9 +167,8 @@ def test_set_when_extra_section():
def test_unset_property(env):
config_unset('core.reporting', env)
_get_missing_value('core.reporting', env)
config_set('core.reporting', 'false', env)
with update_config("core.reporting", None, env):
_get_missing_value('core.reporting', env)
def test_unset_missing_property(env):
@@ -233,35 +224,33 @@ def test_set_core_property(env):
def test_url_validation(env):
key = 'core.dcos_url'
default_value = 'http://dcos.snakeoil.mesosphere.com'
with update_config('core.dcos_url', None, env):
key = 'core.dcos_url'
key2 = 'package.cosmos_url'
key2 = 'package.cosmos_url'
config_set(key, 'http://localhost', env)
config_set(key, 'https://localhost', env)
config_set(key, 'http://dcos-1234', env)
config_set(key2, 'http://dcos-1234.mydomain.com', env)
config_set(key, 'http://localhost', env)
config_set(key, 'https://localhost', env)
config_set(key, 'http://dcos-1234', env)
config_set(key2, 'http://dcos-1234.mydomain.com', env)
config_set(key, 'http://localhost:5050', env)
config_set(key, 'https://localhost:5050', env)
config_set(key, 'http://mesos-1234:5050', env)
config_set(key2, 'http://mesos-1234.mydomain.com:5050', env)
config_set(key, 'http://localhost:5050', env)
config_set(key, 'https://localhost:5050', env)
config_set(key, 'http://mesos-1234:5050', env)
config_set(key2, 'http://mesos-1234.mydomain.com:5050', env)
config_set(key, 'http://localhost:8080', env)
config_set(key, 'https://localhost:8080', env)
config_set(key, 'http://marathon-1234:8080', env)
config_set(key2, 'http://marathon-1234.mydomain.com:5050', env)
config_set(key, 'http://localhost:8080', env)
config_set(key, 'https://localhost:8080', env)
config_set(key, 'http://marathon-1234:8080', env)
config_set(key2, 'http://marathon-1234.mydomain.com:5050', env)
config_set(key, 'http://user@localhost:8080', env)
config_set(key, 'http://u-ser@localhost:8080', env)
config_set(key, 'http://user123_@localhost:8080', env)
config_set(key, 'http://user:p-ssw_rd@localhost:8080', env)
config_set(key, 'http://user123:password321@localhost:8080', env)
config_set(key2, 'http://us%r1$3:pa#sw*rd321@localhost:8080', env)
config_set(key, 'http://user@localhost:8080', env)
config_set(key, 'http://u-ser@localhost:8080', env)
config_set(key, 'http://user123_@localhost:8080', env)
config_set(key, 'http://user:p-ssw_rd@localhost:8080', env)
config_set(key, 'http://user123:password321@localhost:8080', env)
config_set(key2, 'http://us%r1$3:pa#sw*rd321@localhost:8080', env)
config_set(key, default_value, env)
config_unset(key2, env)
config_unset(key2, env)
def test_fail_url_validation(env):

View File

@@ -1,12 +1,13 @@
import base64
import contextlib
import json
import os
import sys
import pytest
import six
from dcos import subcommand
from dcos import constants, subcommand
from .common import (assert_command, assert_lines, base64_to_dict,
delete_zk_node, delete_zk_nodes, exec_command, file_json,
@@ -18,6 +19,17 @@ from .common import (assert_command, assert_lines, base64_to_dict,
from ..common import file_bytes
@pytest.fixture
def env():
r = os.environ.copy()
r.update({
constants.PATH_ENV: os.environ[constants.PATH_ENV],
constants.DCOS_CONFIG_ENV: os.path.join("tests", "data", "dcos.toml"),
})
return r
def setup_module(module):
setup_universe_server()
@@ -648,11 +660,12 @@ def test_list_cli():
_uninstall_cli_helloworld()
def test_list_cli_only():
def test_list_cli_only(env):
helloworld_path = 'tests/data/package/json/test_list_helloworld_cli.json'
helloworld_json = file_json(helloworld_path)
with _helloworld_cli(), update_config('core.dcos_url', 'http://nohost'):
with _helloworld_cli(), \
update_config('core.dcos_url', 'http://nohost', env):
assert_command(
cmd=['dcos', 'package', 'list', '--json', '--cli'],
stdout=helloworld_json)

View File

@@ -2,7 +2,7 @@ import os
import pytest
from dcos import constants
from dcos import config, constants
from .common import config_set, exec_command, update_config
@@ -22,11 +22,15 @@ def env():
@pytest.yield_fixture(autouse=True)
def setup_env(env):
# token will be removed when we change dcos_url
token = config.get_config_val('core.dcos_acs_token')
config_set("core.dcos_url", "https://dcos.snakeoil.mesosphere.com", env)
config_set("core.dcos_acs_token", token, env)
try:
yield
finally:
config_set("core.dcos_url", "http://dcos.snakeoil.mesosphere.com", env)
config_set("core.dcos_acs_token", token, env)
def test_dont_verify_ssl_with_env_var(env):

View File

@@ -129,6 +129,11 @@ def set_val(name, value):
value_exists = name in toml_config
old_value = toml_config.get(name)
# remove token when core.dcos_url is changed
token_unset = False
if value_exists and old_value != new_value and name == "core.dcos_url":
token_unset = bool(toml_config.pop("core.dcos_acs_token", False))
toml_config[name] = new_value
check_config(toml_config_pre, toml_config, section)
@@ -150,6 +155,10 @@ def set_val(name, value):
else:
msg += "changed from '{}' to '{}'".format(old_value, new_value)
if token_unset:
msg += ("\n[core.dcos_acs_token]: removed\n"
"Please run `dcos auth login` to authenticate to new dcos_url")
return toml_config, msg
@@ -220,13 +229,20 @@ def unset(name):
if section not in toml_config_pre._dictionary:
toml_config_pre._dictionary[section] = {}
value = toml_config.pop(name, None)
if value is None:
raise DCOSException("Property {!r} doesn't exist".format(name))
elif isinstance(value, collections.Mapping):
raise DCOSException(_generate_choice_msg(name, value))
else:
msg = "Removed [{}]".format(name)
# dcos_acs_token is coupled to a specific dcos_url
if name == "core.dcos_url":
unset_token = bool(toml_config.pop("core.dcos_acs_token", None))
if unset_token:
msg += " and [core.dcos_acs_token]"
save(toml_config)
return "Removed [{}]".format(name)
return msg
def _generate_choice_msg(name, value):

View File

@@ -1,12 +1,15 @@
import requests
from requests.auth import AuthBase
from six.moves.urllib.parse import urlparse
from dcos import config, util
from dcos.errors import (DCOSAuthenticationException,
DCOSAuthorizationException, DCOSBadRequest,
DCOSException, DCOSHTTPException,
DCOSUnprocessableException)
logger = util.get_logger(__name__)
DEFAULT_TIMEOUT = 5
@@ -144,12 +147,19 @@ def request(method,
:rtype: Response
"""
auth_token = config.get_config_val(
"core.dcos_acs_token", config.get_config())
if auth_token is None:
auth = None
else:
toml_config = config.get_config()
auth_token = config.get_config_val("core.dcos_acs_token", toml_config)
dcos_url = urlparse(config.get_config_val("core.dcos_url", toml_config))
parsed_url = urlparse(url)
# only request with DC/OS Auth if request is to DC/OS cluster
# request should match scheme + netloc
scheme_eq = parsed_url.scheme == dcos_url.scheme
netloc_eq = parsed_url.netloc == dcos_url.netloc
if auth_token and scheme_eq and netloc_eq:
auth = DCOSAcsAuth(auth_token)
else:
auth = None
response = _request(method, url, is_success, timeout,
auth=auth, verify=verify, **kwargs)