Skip to content

Commit 1562163

Browse files
authored
Merge pull request #34 from IBM/major-release
release v1.0.0
2 parents b905143 + 606a105 commit 1562163

33 files changed

+1606
-845
lines changed

.travis.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
language: python
22
matrix:
33
include:
4-
- python: 2.7
5-
- python: 3.4
64
- python: 3.5
75
- python: 3.6
86
- python: 3.7

README.md

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,87 @@ easy_install --upgrade ibm-cloud-sdk-core
2525
```
2626

2727
## Authentication Types
28-
There are several flavors of authentication supported in this package. To specify the intended authentication pattern to use, the user can pass in the parameter `authentication_type`. This parameter is optional, but it may become required in a future major release. The options for this parameter are `basic`, `iam`, and `icp4d`.
28+
There are several flavors of authentication supported in this package. To specify the intended authentication pattern to use, simply instantiate the `Authenticator` of your choice.
2929

30-
### basic
30+
### Basic
3131
This indicates Basic Auth is to be used. Users will pass in a `username` and `password` and the SDK will generate a Basic Auth header to send with requests to the service.
3232

33-
### iam
34-
This indicates that IAM token authentication is to be used. Users can pass in an `iam_apikey` or an `iam_access_token`. If an API key is used, the SDK will manage the token for the user. In either case, the SDK will generate a Bearer Auth header to send with requests to the service.
33+
```py
34+
from ibm_cloud_sdk_core.authenticators import BasicAuthenticator
3535

36-
### icp4d
37-
This indicates that the service is an instance of ICP4D, which has its own version of token authentication. Users can pass in a `username` and `password`, or an `icp4d_access_token`. If a username and password is given, the SDK will manage the token for the user.
38-
A `icp4d_url` is **required** for this type. In order to use an SDK-managed token with ICP4D authentication, this option **must** be passed in.
36+
authenticator = BasicAuthenticator(<your_username>, <your_password>)
37+
```
38+
39+
### IAM
40+
This indicates that IAM token authentication is to be used. Users can pass in a `apikey` and the SDK will generate a Bearer Auth header to send with requests to the service.
41+
42+
```py
43+
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
44+
45+
authenticator = IAMAuthenticator(<your_apikey>)
46+
```
47+
48+
### Cloud Pak for Data
49+
This indicates that the service is an instance of CP4D, which has its own version of token authentication. Users can pass in a `username`, `password` and `url`, and the SDK will generate a Bearer Auth header to send with requests to the service.
50+
51+
```py
52+
from ibm_cloud_sdk_core.authenticators import CloudPakForDataAuthenticator
53+
54+
authenticator = CloudPakForDataAuthenticator(<your_username>, <your_password>, <your_url>)
55+
```
56+
57+
### Bearer Token
58+
This indicates bearer token authentication is to be used. The system would prepend the `bearer` name to your token and add it to the authorization header.
59+
60+
```py
61+
from ibm_cloud_sdk_core.authenticators import BearerTokenAuthenticator
62+
63+
authenticator = BearerTokenAuthenticator(<your_bearer_token>)
64+
```
65+
66+
### No Authentication
67+
This indicates that no authentication is needed when sending requests to the service
68+
69+
```py
70+
from ibm_cloud_sdk_core.authenticators import NoAuthAuthenticator
71+
72+
authenticator = NoAuthAuthenticator()
73+
```
3974

4075
## Issues
4176

4277
If you encounter an issue with this project, you are welcome to submit a [bug report](https://github.com/IBM/python-sdk-core/issues).
4378
Before opening a new issue, please search for similar issues. It's possible that someone has already reported it.
4479

80+
## Logging
81+
82+
### Enable logging
83+
84+
```python
85+
import logging
86+
logging.basicConfig(level=logging.DEBUG)
87+
```
88+
89+
This would show output of the form:
90+
```
91+
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): iam.cloud.ibm.com:443
92+
DEBUG:urllib3.connectionpool:https://iam.cloud.ibm.com:443 "POST /identity/token HTTP/1.1" 200 1809
93+
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): gateway.watsonplatform.net:443
94+
DEBUG:urllib3.connectionpool:https://gateway.watsonplatform.net:443 "POST /assistant/api/v1/workspaces?version=2018-07-10 HTTP/1.1" 201 None
95+
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): gateway.watsonplatform.net:443
96+
DEBUG:urllib3.connectionpool:https://gateway.watsonplatform.net:443 "GET /assistant/api/v1/workspaces/883a2a44-eb5f-4b1a-96b0-32a90b475ea8?version=2018-07-10&export=true HTTP/1.1" 200 None
97+
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): gateway.watsonplatform.net:443
98+
DEBUG:urllib3.connectionpool:https://gateway.watsonplatform.net:443 "DELETE /assistant/api/v1/workspaces/883a2a44-eb5f-4b1a-96b0-32a90b475ea8?version=2018-07-10 HTTP/1.1" 200 28
99+
```
100+
101+
### Low level request and response dump
102+
To get low level information of the requests/ responses:
103+
104+
```python
105+
from http.client import HTTPConnection
106+
HTTPConnection.debuglevel = 1
107+
```
108+
45109
## Open source @ IBM
46110

47111
Find more open source projects on the [IBM Github Page](http://github.com/IBM)

ibm_cloud_sdk_core/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@
1717
from .detailed_response import DetailedResponse
1818
from .iam_token_manager import IAMTokenManager
1919
from .jwt_token_manager import JWTTokenManager
20-
from .icp4d_token_manager import ICP4DTokenManager
20+
from .cp4d_token_manager import CP4DTokenManager
2121
from .api_exception import ApiException
22-
from .utils import datetime_to_string, string_to_datetime
22+
from .utils import datetime_to_string, string_to_datetime, get_authenticator_from_environment, read_external_sources
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# coding: utf-8
2+
3+
# Copyright 2019 IBM All Rights Reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from .authenticator import Authenticator
18+
from .basic_authenticator import BasicAuthenticator
19+
from .bearer_token_authenticator import BearerTokenAuthenticator
20+
from .cp4d_authenticator import CloudPakForDataAuthenticator
21+
from .iam_authenticator import IAMAuthenticator
22+
from .no_auth_authenticator import NoAuthAuthenticator
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# coding: utf-8
2+
3+
# Copyright 2019 IBM All Rights Reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from abc import ABC, abstractmethod
18+
19+
class Authenticator(ABC):
20+
@abstractmethod
21+
def authenticate(self, req):
22+
"""
23+
Adds the Authorization header, if applicable
24+
"""
25+
pass
26+
27+
@abstractmethod
28+
def validate(self):
29+
"""
30+
Checks if all the inputs needed are present
31+
"""
32+
pass
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# coding: utf-8
2+
3+
# Copyright 2019 IBM All Rights Reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from .authenticator import Authenticator
18+
from ..utils import has_bad_first_or_last_char
19+
import base64
20+
21+
22+
class BasicAuthenticator(Authenticator):
23+
authentication_type = 'basic'
24+
25+
def __init__(self, username, password):
26+
"""
27+
:attr str username: The username
28+
:attr str password: The password
29+
"""
30+
self.username = username
31+
self.password = password
32+
self.validate()
33+
34+
def validate(self):
35+
"""
36+
Performs validation on input params
37+
"""
38+
if self.username is None or self.password is None:
39+
raise ValueError('The username and password shouldn\'t be None.')
40+
41+
if has_bad_first_or_last_char(
42+
self.username) or has_bad_first_or_last_char(self.password):
43+
raise ValueError(
44+
'The username and password shouldn\'t start or end with curly brackets or quotes. '
45+
'Please remove any surrounding {, }, or \" characters.')
46+
47+
def authenticate(self, req):
48+
"""
49+
Adds the Authorization header, if applicable
50+
"""
51+
authstring = "{0}:{1}".format(self.username, self.password)
52+
base64_authorization = base64.b64encode(authstring.encode('utf-8')).decode('utf-8')
53+
54+
headers = req.get('headers')
55+
headers['Authorization'] = 'Basic {0}'.format(base64_authorization)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# coding: utf-8
2+
3+
# Copyright 2019 IBM All Rights Reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from .authenticator import Authenticator
18+
19+
20+
class BearerTokenAuthenticator(Authenticator):
21+
authentication_type = 'bearerToken'
22+
23+
def __init__(self, bearer_token):
24+
"""
25+
:attr str bearer_token: User managed bearer token
26+
"""
27+
self.bearer_token = bearer_token
28+
self.validate()
29+
30+
def validate(self):
31+
"""
32+
Performs validation on input params
33+
"""
34+
if self.bearer_token is None:
35+
raise ValueError('The bearer token shouldn\'t be None.')
36+
37+
def authenticate(self, req):
38+
"""
39+
Adds the Authorization header, if applicable
40+
"""
41+
headers = req.get('headers')
42+
headers['Authorization'] = 'Bearer {0}'.format(self.bearer_token)
43+
44+
def set_bearer_token(self, bearer_token):
45+
"""
46+
Sets the bearer token
47+
"""
48+
self.bearer_token = bearer_token
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# coding: utf-8
2+
3+
# Copyright 2019 IBM All Rights Reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from .authenticator import Authenticator
18+
from ..cp4d_token_manager import CP4DTokenManager
19+
from ..utils import has_bad_first_or_last_char
20+
21+
22+
class CloudPakForDataAuthenticator(Authenticator):
23+
authentication_type = 'cp4d'
24+
25+
def __init__(self,
26+
username,
27+
password,
28+
url,
29+
disable_ssl_verification=False,
30+
headers=None,
31+
proxies=None):
32+
"""
33+
:attr str username: The username
34+
:attr str password: The password
35+
:attr str url: The url for authentication
36+
:attr bool disable_ssl_verification: enables/ disabled ssl verification
37+
:attr dict headers: user-defined headers
38+
:attr dict proxies: user-defined proxies
39+
"""
40+
self.token_manager = CP4DTokenManager(
41+
username, password, url, disable_ssl_verification, headers, proxies)
42+
self.validate()
43+
44+
def validate(self):
45+
"""
46+
Performs validation on input params
47+
"""
48+
if self.token_manager.username is None or self.token_manager.password is None:
49+
raise ValueError('The username and password shouldn\'t be None.')
50+
51+
if self.token_manager.url is None:
52+
raise ValueError('The url shouldn\'t be None.')
53+
54+
if has_bad_first_or_last_char(
55+
self.token_manager.username) or has_bad_first_or_last_char(self.token_manager.password):
56+
raise ValueError(
57+
'The username and password shouldn\'t start or end with curly brackets or quotes. '
58+
'Please remove any surrounding {, }, or \" characters.')
59+
60+
if has_bad_first_or_last_char(self.token_manager.url):
61+
raise ValueError(
62+
'The url shouldn\'t start or end with curly brackets or quotes. '
63+
'Please remove any surrounding {, }, or \" characters.')
64+
65+
def authenticate(self, req):
66+
"""
67+
Adds the Authorization header, if applicable
68+
"""
69+
headers = req.get('headers')
70+
bearer_token = self.token_manager.get_token()
71+
headers['Authorization'] = 'Bearer {0}'.format(bearer_token)
72+
73+
def set_disable_ssl_verification(self, status=False):
74+
"""
75+
Sets the ssl verification to enabled or disabled
76+
"""
77+
self.token_manager.set_disable_ssl_verification(status)
78+
79+
def set_headers(self, headers):
80+
"""
81+
Sets user-defined headers
82+
"""
83+
self.token_manager.set_headers(headers)
84+
85+
def set_proxies(self, proxies):
86+
"""
87+
Sets the proxies
88+
"""
89+
self.token_manager.set_proxies(proxies)

0 commit comments

Comments
 (0)