Skip to content

Commit 7eb7e88

Browse files
authored
Merge pull request #21 from IBM/auth
New Authentication mechanism
2 parents ed2147a + cec3609 commit 7eb7e88

32 files changed

+1445
-815
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: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,52 @@ easy_install --upgrade ibm-cloud-sdk-core
2121
```
2222

2323
## Authentication Types
24-
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`.
24+
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.
2525

26-
### basic
26+
### Basic
2727
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.
2828

29-
### iam
30-
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.
29+
```py
30+
from ibm_cloud_sdk_core.authenticators import BasicAuthenticator
3131

32-
### icp4d
33-
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.
34-
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.
32+
authenticator = BasicAuthenticator(<your_username>, <your_password>)
33+
```
34+
35+
### IAM
36+
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.
37+
38+
```py
39+
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
40+
41+
authenticator = IAMAuthenticator(<your_apikey>)
42+
```
43+
44+
### Cloud Pak for Data
45+
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.
46+
47+
```py
48+
from ibm_cloud_sdk_core.authenticators import CloudPakForDataAuthenticator
49+
50+
authenticator = CloudPakForDataAuthenticator(<your_username>, <your_password>, <your_url>)
51+
```
52+
53+
### Bearer Token
54+
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.
55+
56+
```py
57+
from ibm_cloud_sdk_core.authenticators import BearerTokenAuthenticator
58+
59+
authenticator = BearerTokenAuthenticator(<your_bearer_token>)
60+
```
61+
62+
### No Authentication
63+
This indicates that no authentication is needed when sending requests to the service
64+
65+
```py
66+
from ibm_cloud_sdk_core.authenticators import NoAuthAuthenticator
67+
68+
authenticator = NoAuthAuthenticator()
69+
```
3570

3671
## Issues
3772

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
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)