Use utf-8 & properly parse hostname from registry URL

This commit is contained in:
Christian M. Adams
2021-05-20 11:47:52 -04:00
parent 8316a1d198
commit cea6d8c3cb
3 changed files with 23 additions and 14 deletions

View File

@@ -2,6 +2,7 @@ import collections
import json import json
import logging import logging
from base64 import b64encode from base64 import b64encode
from urllib import parse as urlparse
from django.conf import settings from django.conf import settings
from kubernetes import client, config from kubernetes import client, config
@@ -52,19 +53,26 @@ class PodManager(object):
return pods return pods
@classmethod
def create_secret(self, job): def create_secret(self, job):
task = collections.namedtuple('Task', 'id instance_group')(id='', instance_group=job.instance_group)
pm = PodManager(task)
registry_cred = job.execution_environment.credential registry_cred = job.execution_environment.credential
host = registry_cred.get_input('host').split('/')[0] host = registry_cred.get_input('host')
scheme = 'https'
# urlparse requires '//' to be provided if scheme is not specified
original_parsed = urlparse.urlsplit(host)
if (not original_parsed.scheme and not host.startswith('//')) or original_parsed.hostname is None:
host = '%s://%s' % (scheme, host)
parsed = urlparse.urlsplit(host)
host = parsed.hostname
if parsed.port:
host = "{0}:{1}".format(host, parsed.port)
username = registry_cred.get_input("username") username = registry_cred.get_input("username")
password = registry_cred.get_input("password") password = registry_cred.get_input("password")
# Construct container auth dict and base64 encode it # Construct container auth dict and base64 encode it
token = b64encode("{}:{}".format(username, password).encode('ascii')).decode() token = b64encode("{}:{}".format(username, password).encode('UTF-8')).decode()
auth_dict = json.dumps({"auths": {host: {"auth": token}}}, indent=4) auth_dict = json.dumps({"auths": {host: {"auth": token}}}, indent=4)
auth_data = b64encode(str(auth_dict).encode('ascii')).decode() auth_data = b64encode(str(auth_dict).encode('UTF-8')).decode()
# Construct Secret object # Construct Secret object
secret = client.V1Secret() secret = client.V1Secret()
@@ -77,7 +85,7 @@ class PodManager(object):
# Check if secret already exists # Check if secret already exists
secrets = None secrets = None
try: try:
secrets = pm.kube_api.list_namespaced_secret(namespace=pm.namespace) secrets = self.kube_api.list_namespaced_secret(namespace=self.namespace)
except client.rest.ApiException: except client.rest.ApiException:
error_msg = 'Invalid openshift or k8s cluster credential' error_msg = 'Invalid openshift or k8s cluster credential'
logger.exception(error_msg) logger.exception(error_msg)
@@ -90,20 +98,21 @@ class PodManager(object):
for s in secrets_dict: for s in secrets_dict:
if s['metadata']['name'] == secret_name: if s['metadata']['name'] == secret_name:
secret_exists = True secret_exists = True
break
if secret_exists: if secret_exists:
try: try:
# Try to replace existing secret # Try to replace existing secret
pm.kube_api.delete_namespaced_secret(name=secret.metadata.name, namespace=pm.namespace) self.kube_api.delete_namespaced_secret(name=secret.metadata.name, namespace=self.namespace)
pm.kube_api.create_namespaced_secret(namespace=pm.namespace, body=secret) self.kube_api.create_namespaced_secret(namespace=self.namespace, body=secret)
except Exception: except Exception:
error_msg = 'Failed to create imagePullSecret for container group {}'.format(task.instance_group.name) error_msg = 'Failed to create imagePullSecret for container group {}'.format(job.instance_group.name)
logger.exception(error_msg) logger.exception(error_msg)
job.cancel(job_explanation=error_msg) job.cancel(job_explanation=error_msg)
raise raise
else: else:
# Create an image pull secret in namespace # Create an image pull secret in namespace
try: try:
pm.kube_api.create_namespaced_secret(namespace=pm.namespace, body=secret) self.kube_api.create_namespaced_secret(namespace=self.namespace, body=secret)
except client.rest.ApiException as e: except client.rest.ApiException as e:
if e.status == 401: if e.status == 401:
error_msg = 'Failed to create imagePullSecret: {}. Check that openshift or k8s credential has permission to create a secret.'.format( error_msg = 'Failed to create imagePullSecret: {}. Check that openshift or k8s credential has permission to create a secret.'.format(
@@ -112,7 +121,7 @@ class PodManager(object):
logger.exception(error_msg) logger.exception(error_msg)
# let job run for the case that the secret exists but the cluster cred doesn't have permission to create a secret # let job run for the case that the secret exists but the cluster cred doesn't have permission to create a secret
except Exception: except Exception:
error_msg = 'Failed to create imagePullSecret for container group {}'.format(task.instance_group.name) error_msg = 'Failed to create imagePullSecret for container group {}'.format(job.instance_group.name)
logger.exception(error_msg) logger.exception(error_msg)
job.cancel(job_explanation=error_msg) job.cancel(job_explanation=error_msg)

View File

@@ -842,7 +842,7 @@ class BaseTask(object):
username = cred.get_input('username') username = cred.get_input('username')
password = cred.get_input('password') password = cred.get_input('password')
token = "{}:{}".format(username, password) token = "{}:{}".format(username, password)
auth_data = {'auths': {host: {'auth': b64encode(token.encode('ascii')).decode()}}} auth_data = {'auths': {host: {'auth': b64encode(token.encode('UTF-8')).decode('UTF-8')}}}
authfile.write(json.dumps(auth_data, indent=4)) authfile.write(json.dumps(auth_data, indent=4))
params["container_options"].append(f'--authfile={authfile.name}') params["container_options"].append(f'--authfile={authfile.name}')
else: else:

View File

@@ -51,7 +51,7 @@ def construct_rsyslog_conf_template(settings=settings):
# urlparse requires '//' to be provided if scheme is not specified # urlparse requires '//' to be provided if scheme is not specified
original_parsed = urlparse.urlsplit(host) original_parsed = urlparse.urlsplit(host)
if (not original_parsed.scheme and not host.startswith('//')) or original_parsed.hostname is None: if (not original_parsed.scheme and not host.startswith('//')) or original_parsed.hostname is None:
host = '%s://%s' % (scheme, host) if scheme else '//%s' % host host = '%s://%s' % (scheme, host)
parsed = urlparse.urlsplit(host) parsed = urlparse.urlsplit(host)
host = escape_quotes(parsed.hostname) host = escape_quotes(parsed.hostname)