Skip to content

Commit 6186be6

Browse files
authored
Add build_from_cf_config() to use cf login credentials (#175)
* Add build_from_cf_config() to allow using credentials from a previous cf login Authored-by: Sven Hergenhahn <sven.hergenhahn@dm.de> See #172
1 parent da83f20 commit 6186be6

3 files changed

Lines changed: 59 additions & 2 deletions

File tree

README.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,19 @@ To instantiate the client, nothing easier
7373
client.refresh_token = 'refresh-token'
7474
client._access_token = 'access-token'
7575
76+
You can also instantiate the client by reading the config file generated by `cf login`, which allows for authenticating via SSO and LDAP:
77+
78+
.. code-block:: python
79+
80+
# init with endpoint & token from the cf cli config file
81+
from cloudfoundry_client.client import CloudFoundryClient
82+
83+
# use the default file, i.e. ~/.cf/config.json
84+
client = CloudFoundryClient.build_from_cf_config()
85+
# or specify an alternative path
86+
# - other kwargs can be passed through to CloudFoundryClient instantiation
87+
client = CloudFoundryClient.build_from_cf_config(config_path="some/path/config.json", proxy=proxy, verify=False)
88+
7689
It can also be instantiated with oauth code flow if you possess a dedicated oauth application with its redirection
7790

7891
.. code-block:: python

main/cloudfoundry_client/client.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import logging
2+
from pathlib import Path
3+
import json
24
from http import HTTPStatus
35
from typing import Optional
46

@@ -120,8 +122,8 @@ def __init__(self, target_endpoint: str, credential_manager: "CloudFoundryClient
120122

121123
class CloudFoundryClient(CredentialManager):
122124
def __init__(self, target_endpoint: str, client_id: str = "cf", client_secret: str = "", **kwargs):
123-
""" "
124-
:param target_endpoint :the target endpoint
125+
"""
126+
:param target_endpoint :the target endpoint.
125127
:param client_id: the client_id
126128
:param client_secret: the client secret
127129
:param proxy: a dict object with entries http and https
@@ -206,6 +208,19 @@ def _get_info(self, target_endpoint: str, proxy: Optional[dict] = None, verify:
206208
log_stream.get("href") if log_stream is not None else None,
207209
)
208210

211+
@staticmethod
212+
def build_from_cf_config(config_path: Optional[str] = None, **kwargs) -> 'CloudFoundryClient':
213+
config = Path(config_path) if config_path else Path.home() / '.cf/config.json'
214+
try:
215+
with open(config) as f:
216+
cf_config = json.load(f)
217+
except Exception as e:
218+
_logger.critical('Could not retrieve cf config: %s', e)
219+
raise
220+
client = CloudFoundryClient(cf_config['Target'], **kwargs)
221+
client.init_with_token(cf_config['RefreshToken'])
222+
return client
223+
209224
@staticmethod
210225
def _resolve_login_endpoint(root_links):
211226
return (root_links.get("login") or root_links.get("uaa") or root_links.get("self"))["href"]

test/test_client.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
from os import remove as file_remove
23
import unittest
34
from http import HTTPStatus
45
from unittest.mock import patch
@@ -89,6 +90,34 @@ def test_refresh_request_with_token_format_opaque(self):
8990
verify=True,
9091
)
9192

93+
def test_refresh_request_with_token_from_cf_config(self):
94+
requests = FakeRequests()
95+
session = MockSession()
96+
proxy = dict(http='', https='')
97+
cf_config_file_content = {"Target": self.TARGET_ENDPOINT, "RefreshToken": "refresh-token"}
98+
with open("config.json", "w", encoding="utf-8") as f:
99+
json.dump(cf_config_file_content, f, ensure_ascii=False, indent=4)
100+
with patch("oauth2_client.credentials_manager.requests", new=requests), patch(
101+
"cloudfoundry_client.client.requests", new=requests
102+
):
103+
requests.Session.return_value = session
104+
self._mock_info_calls(requests)
105+
requests.post.return_value = MockResponse(
106+
"%s/oauth/token" % self.AUTHORIZATION_ENDPOINT,
107+
status_code=HTTPStatus.OK.value,
108+
text=json.dumps(dict(access_token="access-token", refresh_token="refresh-token")),
109+
)
110+
client = CloudFoundryClient.build_from_cf_config("config.json", proxy=proxy, verify=True) # noqa: F841
111+
file_remove('config.json')
112+
self.assertEqual("Bearer access-token", session.headers.get("Authorization"))
113+
requests.post.assert_called_with(
114+
requests.post.return_value.url,
115+
data=dict(grant_type="refresh_token", scope="", refresh_token="refresh-token"),
116+
headers=dict(Accept="application/json", Authorization="Basic Y2Y6"),
117+
proxies=proxy,
118+
verify=True,
119+
)
120+
92121
def test_grant_password_request_with_login_hint(self):
93122
requests = FakeRequests()
94123
session = MockSession()

0 commit comments

Comments
 (0)