Skip to content

Commit

Permalink
Merge pull request #6254 from memsharded/feature/http_basic_ping
Browse files Browse the repository at this point in the history
Use HttpBasic auth in the ping API endpoint for the "conan user" command.
  • Loading branch information
lasote committed Dec 20, 2019
2 parents 9951a2e + 03ec3bd commit 247579f
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 23 deletions.
6 changes: 3 additions & 3 deletions conans/client/rest/rest_client.py
Expand Up @@ -46,12 +46,12 @@ def __init__(self, remote, token, refresh_token, custom_headers, output, request
# This dict is shared for all the instances of RestApiClient
self._cached_capabilities = cached_capabilities

def _capable(self, capability):
def _capable(self, capability, user=None, password=None):
capabilities = self._cached_capabilities.get(self._remote_url)
if capabilities is None:
tmp = RestV1Methods(self._remote_url, self._token, self._custom_headers, self._output,
self._requester, self._verify_ssl, self._artifacts_properties)
capabilities = tmp.server_capabilities()
capabilities = tmp.server_capabilities(user, password)
self._cached_capabilities[self._remote_url] = capabilities
logger.debug("REST: Cached capabilities for the remote: %s" % capabilities)
if not self._revisions_enabled and ONLY_V2 in capabilities:
Expand Down Expand Up @@ -116,7 +116,7 @@ def authenticate(self, user, password):
else:
try:
# Check capabilities can raise also 401 until the new Artifactory is released
oauth_capable = self._capable(OAUTH_TOKEN)
oauth_capable = self._capable(OAUTH_TOKEN, user, password)
except AuthenticationException:
oauth_capable = False

Expand Down
11 changes: 7 additions & 4 deletions conans/client/rest/rest_client_common.py
Expand Up @@ -149,13 +149,16 @@ def check_credentials(self):
verify=self.verify_ssl)
return ret

def server_capabilities(self):
def server_capabilities(self, user=None, password=None):
"""Get information about the server: status, version, type and capabilities"""
url = self.router.ping()
logger.debug("REST: ping: %s" % url)

ret = self.requester.get(url, auth=self.auth, headers=self.custom_headers,
verify=self.verify_ssl)
if user and password:
# This can happen in "conan user" cmd. Instead of empty token, use HttpBasic
auth = HTTPBasicAuth(user, password)
else:
auth = self.auth
ret = self.requester.get(url, auth=auth, headers=self.custom_headers, verify=self.verify_ssl)

server_capabilities = ret.headers.get('X-Conan-Server-Capabilities', "")
if not server_capabilities and not ret.ok:
Expand Down
47 changes: 31 additions & 16 deletions conans/test/functional/remote/auth_test.py
Expand Up @@ -32,7 +32,7 @@ def setUp(self):
[(str(self.ref), "pepe,nacho@gmail.com")], # write permissions
users={"lasote": "mypass",
"pepe": "pepepass",
"nacho@gmail.com": "nachopass",}) # exported users and passwords
"nacho@gmail.com": "nachopass"}) # exported creds
self.servers["default"] = self.test_server

def retries_test(self):
Expand Down Expand Up @@ -134,22 +134,37 @@ class RequesterMock(object):
def __init__(self, *args, **kwargs):
pass

def get(self, url, *args, **kwargs):
@staticmethod
def get(url, **kwargs):
resp_basic_auth = Response()
resp_basic_auth.status_code = 200
if "authenticate" in url:
resp_basic_auth = Response()
if kwargs["auth"].password != "PASSWORD!":
raise Exception("Bad password")
resp_basic_auth._content = b"TOKEN"
resp_basic_auth.status_code = 200
resp_basic_auth.headers = {"Content-Type": "text/plain"}
return resp_basic_auth

if "ping" in url and not kwargs["auth"].token:
raise AuthenticationException(
"I'm an Artifactory without anonymous access that "
"requires authentication for the ping endpoint and "
"I don't return the capabilities")
raise Exception("Shouldn't be more remote calls")

self.client = TestClient(requester_class=RequesterMock, default_server_user=True)
self.client.run("user user -p password -r default")
elif "ping" in url:
token = getattr(kwargs["auth"], "token", None)
password = getattr(kwargs["auth"], "password", None)
if token and token != "TOKEN":
raise Exception("Bad JWT Token")
if not token and not password:
raise AuthenticationException(
"I'm an Artifactory without anonymous access that "
"requires authentication for the ping endpoint and "
"I don't return the capabilities")
elif "search" in url:
if kwargs["auth"].token != "TOKEN":
raise Exception("Bad JWT Token")
resp_basic_auth._content = b'{"results": []}'
resp_basic_auth.headers = {"Content-Type": "application/json"}
else:
raise Exception("Shouldn't be more remote calls")
return resp_basic_auth

client = TestClient(requester_class=RequesterMock, default_server_user=True)
client.run("user user -p PASSWORD! -r=default")
self.assertIn("Changed user of remote 'default' from 'None' (anonymous) to 'user'",
self.client.out)
client.out)
client.run("search pkg -r=default")
self.assertIn("There are no packages matching the 'pkg' pattern", client.out)

0 comments on commit 247579f

Please sign in to comment.