forked from kubeflow/pipelines
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add SDK API to create Creds (kubeflow#288)
* Add SDK API to create Creds * try to resolve unit test timeout
- Loading branch information
1 parent
9cbe5e1
commit 5c957ba
Showing
8 changed files
with
429 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
# Copyright 2019 The Kubeflow Authors. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import logging | ||
import json | ||
import configparser | ||
from os.path import expanduser | ||
|
||
from kubernetes import client | ||
from ..constants import constants | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def set_gcs_credentials(namespace, credentials_file, service_account): | ||
''' | ||
Set GCS Credentails (secret and service account) with credentials file. | ||
Args: | ||
namespace(str): The kubernetes namespace. | ||
credentials_file(str): The path for the gcs credentials file. | ||
service_account(str): The name of service account. If the service_account | ||
is specified, will attach created secret with the service account, | ||
otherwise will create new one and attach with created secret. | ||
''' | ||
|
||
with open(expanduser(credentials_file)) as f: | ||
gcs_creds_content = f.read() | ||
|
||
# Try to get GCS creds file name from configmap, set default value then if cannot. | ||
gcs_creds_file_name = get_creds_name_from_config_map( | ||
'gcsCredentialFileName') | ||
if not gcs_creds_file_name: | ||
gcs_creds_file_name = constants.GCS_CREDS_FILE_DEFAULT_NAME | ||
|
||
string_data = {gcs_creds_file_name: gcs_creds_content} | ||
|
||
secret_name = create_secret( | ||
namespace=namespace, string_data=string_data) | ||
|
||
set_service_account(namespace=namespace, | ||
service_account=service_account, | ||
secret_name=secret_name) | ||
|
||
|
||
def set_s3_credentials(namespace, credentials_file, service_account, s3_profile='default', # pylint: disable=too-many-locals,too-many-arguments | ||
s3_endpoint=None, s3_region=None, s3_use_https=None, s3_verify_ssl=None): # pylint: disable=unused-argument | ||
''' | ||
Set S3 Credentails (secret and service account). | ||
Args: | ||
namespace(str): The kubernetes namespace. | ||
credentials_file(str): The path for the S3 credentials file. | ||
s3_profile(str): The profile for S3, default value is 'default'. | ||
service_account(str): The name of service account(Optional). If the service_account | ||
is specified, will attach created secret with the service account, | ||
otherwise will create new one and attach with created secret. | ||
s3_endpoint(str): S3 settings variable S3_ENDPOINT. | ||
s3_region(str): S3 settings variable AWS_REGION. | ||
s3_use_https(str): S3 settings variable S3_USE_HTTPS. | ||
s3_verify_ssl(str): S3 settings variable S3_VERIFY_SSL. | ||
''' | ||
|
||
config = configparser.ConfigParser() | ||
config.read([expanduser(credentials_file)]) | ||
s3_access_key_id = config.get(s3_profile, 'aws_access_key_id') | ||
s3_secret_access_key = config.get( | ||
s3_profile, 'aws_secret_access_key') | ||
|
||
# Try to get S3 creds name from configmap, set default value then if cannot. | ||
s3_access_key_id_name = get_creds_name_from_config_map( | ||
's3AccessKeyIDName') | ||
if not s3_access_key_id_name: | ||
s3_access_key_id_name = constants.S3_ACCESS_KEY_ID_DEFAULT_NAME | ||
|
||
s3_secret_access_key_name = get_creds_name_from_config_map( | ||
's3SecretAccessKeyName') | ||
if not s3_secret_access_key_name: | ||
s3_secret_access_key_name = constants.S3_SECRET_ACCESS_KEY_DEFAULT_NAME | ||
|
||
data = { | ||
s3_access_key_id_name: s3_access_key_id, | ||
s3_secret_access_key_name: s3_secret_access_key, | ||
} | ||
|
||
s3_cred_sets = { | ||
's3_endpoint': constants.KFSERVING_GROUP + "/s3-endpoint", | ||
's3_region': constants.KFSERVING_GROUP + "/s3-region", | ||
's3_use_https': constants.KFSERVING_GROUP + "/s3-usehttps", | ||
's3_verify_ssl': constants.KFSERVING_GROUP + "/s3-verifyssl", | ||
} | ||
|
||
s3_annotations = {} | ||
for key, value in s3_cred_sets.items(): | ||
arg = vars()[key] | ||
if arg is not None: | ||
s3_annotations.update({value: arg}) | ||
|
||
secret_name = create_secret( | ||
namespace=namespace, annotations=s3_annotations, data=data) | ||
|
||
set_service_account(namespace=namespace, | ||
service_account=service_account, | ||
secret_name=secret_name) | ||
|
||
|
||
def create_secret(namespace, annotations=None, data=None, string_data=None): | ||
'Create namespaced secret, and return the secret name.' | ||
try: | ||
created_secret = client.CoreV1Api().create_namespaced_secret( | ||
namespace, | ||
client.V1Secret( | ||
api_version='v1', | ||
kind='Secret', | ||
metadata=client.V1ObjectMeta( | ||
generate_name=constants.DEFAULT_SECRET_NAME, | ||
annotations=annotations), | ||
data=data, | ||
string_data=string_data)) | ||
except client.rest.ApiException as e: | ||
raise RuntimeError( | ||
"Exception when calling CoreV1Api->create_namespaced_secret: %s\n" % e) | ||
|
||
secret_name = created_secret.metadata.name | ||
logger.info('Created Secret: %s in namespace %s', secret_name, namespace) | ||
return secret_name | ||
|
||
|
||
def set_service_account(namespace, service_account, secret_name): | ||
'''Set service account, create if service_account does not exist, otherwise patch it.''' | ||
if check_sa_exists(namespace=namespace, service_account=service_account): | ||
patch_service_account(secret_name=secret_name, | ||
namespace=namespace, | ||
sa_name=service_account) | ||
else: | ||
create_service_account(secret_name=secret_name, | ||
namespace=namespace, | ||
sa_name=service_account) | ||
|
||
|
||
def check_sa_exists(namespace, service_account): | ||
'''Check if the specified service account existing.''' | ||
sa_list = client.CoreV1Api().list_namespaced_service_account(namespace=namespace) | ||
|
||
sa_name_list = [] | ||
for item in range(0, len(sa_list.items)-1): | ||
sa_name_list.append(sa_list.items[item].metadata.name) | ||
|
||
if service_account in sa_name_list: | ||
return True | ||
|
||
return False | ||
|
||
|
||
def create_service_account(secret_name, namespace, sa_name): | ||
'Create namespaced service account, and return the service account name' | ||
try: | ||
client.CoreV1Api().create_namespaced_service_account( | ||
namespace, | ||
client.V1ServiceAccount( | ||
metadata=client.V1ObjectMeta( | ||
name=sa_name | ||
), | ||
secrets=[client.V1ObjectReference( | ||
kind='Secret', | ||
name=secret_name)])) | ||
except client.rest.ApiException as e: | ||
raise RuntimeError( | ||
"Exception when calling CoreV1Api->create_namespaced_service_account: %s\n" % e) | ||
|
||
logger.info('Created Service account: %s in namespace %s', sa_name, namespace) | ||
|
||
|
||
def patch_service_account(secret_name, namespace, sa_name): | ||
'Patch namespaced service account to attach with created secret.' | ||
try: | ||
client.CoreV1Api().patch_namespaced_service_account( | ||
sa_name, | ||
namespace, | ||
client.V1ServiceAccount( | ||
secrets=[client.V1ObjectReference( | ||
kind='Secret', | ||
name=secret_name)])) | ||
except client.rest.ApiException as e: | ||
raise RuntimeError( | ||
"Exception when calling CoreV1Api->patch_namespaced_service_account: %s\n" % e) | ||
|
||
logger.info('Pacthed Service account: %s in namespace %s', sa_name, namespace) | ||
|
||
|
||
def get_creds_name_from_config_map(creds): | ||
'''Get the credentials name from kfservice config map.''' | ||
try: | ||
kfsvc_config_map = client.CoreV1Api().read_namespaced_config_map( | ||
constants.KFSERVICE_CONFIG_MAP_NAME, | ||
constants.KFSERVICE_SYSTEM_NAMESPACE) | ||
except client.rest.ApiException as e: | ||
raise RuntimeError( | ||
"Exception when calling CoreV1Api->read_namespaced_config_map: %s\n" % e) | ||
|
||
kfsvc_creds_str = kfsvc_config_map.data['credentials'] | ||
kfsvc_creds_json = json.loads(kfsvc_creds_str) | ||
|
||
if creds == 'gcsCredentialFileName': | ||
return kfsvc_creds_json['gcs']['gcsCredentialFileName'] | ||
elif creds == 's3AccessKeyIDName': | ||
return kfsvc_creds_json['s3']['s3AccessKeyIDName'] | ||
elif creds == 's3SecretAccessKeyName': | ||
return kfsvc_creds_json['s3']['s3SecretAccessKeyName'] | ||
else: | ||
raise RuntimeError("Unknown credentials.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[default] | ||
aws_access_key_id = ARQ7AKIBFOFN6F6WXBSZ | ||
aws_secret_access_key = 4tdCyzIxlbPzoBfQGbAPw2hY+Rkzgv/b4vB0Q+ps |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"client_id": "760518506408-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com", | ||
"client_secret": "d-FL95Q19q7MQmHD0TyFpd7h", | ||
"refresh_token": "1/bqYmkxnDbxEstG12XcmOZrN0-eyI3beanJbRd4kqs6g", | ||
"type": "authorized_user" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.