| # Copyright 2014 Rackspace Australia |
| # |
| # 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 hmac |
| from hashlib import sha1 |
| import logging |
| from time import time |
| import os |
| import random |
| import six |
| from six.moves import urllib |
| import string |
| |
| |
| class Swift(object): |
| log = logging.getLogger("zuul.lib.swift") |
| |
| def __init__(self, config): |
| self.config = config |
| self.connection = False |
| if self.config.has_option('swift', 'X-Account-Meta-Temp-Url-Key'): |
| self.secure_key = self.config.get('swift', |
| 'X-Account-Meta-Temp-Url-Key') |
| else: |
| self.secure_key = ''.join( |
| random.choice(string.ascii_uppercase + string.digits) |
| for x in range(20) |
| ) |
| |
| self.storage_url = '' |
| if self.config.has_option('swift', 'X-Storage-Url'): |
| self.storage_url = self.config.get('swift', 'X-Storage-Url') |
| |
| try: |
| if self.config.has_section('swift'): |
| if (not self.config.has_option('swift', 'Send-Temp-Url-Key') |
| or self.config.getboolean('swift', |
| 'Send-Temp-Url-Key')): |
| self.connect() |
| |
| # Tell swift of our key |
| headers = {} |
| headers['X-Account-Meta-Temp-Url-Key'] = self.secure_key |
| self.connection.post_account(headers) |
| |
| if not self.config.has_option('swift', 'X-Storage-Url'): |
| self.connect() |
| self.storage_url = self.connection.get_auth()[0] |
| except Exception as e: |
| self.log.warning("Unable to set up swift. Signed storage URL is " |
| "likely to be wrong. %s" % e) |
| |
| def connect(self): |
| if not self.connection: |
| authurl = self.config.get('swift', 'authurl') |
| |
| user = (self.config.get('swift', 'user') |
| if self.config.has_option('swift', 'user') else None) |
| key = (self.config.get('swift', 'key') |
| if self.config.has_option('swift', 'key') else None) |
| retries = (self.config.get('swift', 'retries') |
| if self.config.has_option('swift', 'retries') else 5) |
| preauthurl = (self.config.get('swift', 'preauthurl') |
| if self.config.has_option('swift', 'preauthurl') |
| else None) |
| preauthtoken = (self.config.get('swift', 'preauthtoken') |
| if self.config.has_option('swift', 'preauthtoken') |
| else None) |
| snet = (self.config.get('swift', 'snet') |
| if self.config.has_option('swift', 'snet') else False) |
| starting_backoff = (self.config.get('swift', 'starting_backoff') |
| if self.config.has_option('swift', |
| 'starting_backoff') |
| else 1) |
| max_backoff = (self.config.get('swift', 'max_backoff') |
| if self.config.has_option('swift', 'max_backoff') |
| else 64) |
| tenant_name = (self.config.get('swift', 'tenant_name') |
| if self.config.has_option('swift', 'tenant_name') |
| else None) |
| auth_version = (self.config.get('swift', 'auth_version') |
| if self.config.has_option('swift', 'auth_version') |
| else 2.0) |
| cacert = (self.config.get('swift', 'cacert') |
| if self.config.has_option('swift', 'cacert') else None) |
| insecure = (self.config.get('swift', 'insecure') |
| if self.config.has_option('swift', 'insecure') |
| else False) |
| ssl_compression = (self.config.get('swift', 'ssl_compression') |
| if self.config.has_option('swift', |
| 'ssl_compression') |
| else True) |
| |
| available_os_options = ['tenant_id', 'auth_token', 'service_type', |
| 'endpoint_type', 'tenant_name', |
| 'object_storage_url', 'region_name'] |
| |
| os_options = {} |
| for os_option in available_os_options: |
| if self.config.has_option('swift', os_option): |
| os_options[os_option] = self.config.get('swift', os_option) |
| |
| import swiftclient |
| self.connection = swiftclient.client.Connection( |
| authurl=authurl, user=user, key=key, retries=retries, |
| preauthurl=preauthurl, preauthtoken=preauthtoken, snet=snet, |
| starting_backoff=starting_backoff, max_backoff=max_backoff, |
| tenant_name=tenant_name, os_options=os_options, |
| auth_version=auth_version, cacert=cacert, insecure=insecure, |
| ssl_compression=ssl_compression) |
| |
| def generate_form_post_middleware_params(self, destination_prefix='', |
| **kwargs): |
| """Generate the FormPost middleware params for the given settings""" |
| |
| # Define the available settings and their defaults |
| settings = { |
| 'container': '', |
| 'expiry': 7200, |
| 'max_file_size': 104857600, |
| 'max_file_count': 10, |
| 'file_path_prefix': '' |
| } |
| |
| for key, default in six.iteritems(settings): |
| # TODO(jeblair): Remove the following two lines after a |
| # deprecation period for the underscore variants of the |
| # settings in YAML. |
| if key in kwargs: |
| settings[key] = kwargs[key] |
| # Since we prefer '-' rather than '_' in YAML, look up |
| # keys there using hyphens. Continue to use underscores |
| # everywhere else. |
| altkey = key.replace('_', '-') |
| if altkey in kwargs: |
| settings[key] = kwargs[altkey] |
| elif self.config.has_option('swift', 'default_' + key): |
| settings[key] = self.config.get('swift', 'default_' + key) |
| # TODO: these are always strings; some should be converted |
| # to ints. |
| |
| expires = int(time() + int(settings['expiry'])) |
| redirect = '' |
| |
| url = os.path.join(self.storage_url, settings['container'], |
| settings['file_path_prefix'], |
| destination_prefix) |
| u = urllib.parse.urlparse(url) |
| |
| hmac_body = '%s\n%s\n%s\n%s\n%s' % (u.path, redirect, |
| settings['max_file_size'], |
| settings['max_file_count'], |
| expires) |
| |
| signature = hmac.new(self.secure_key, hmac_body, sha1).hexdigest() |
| |
| return url, hmac_body, signature |