seporaitis / yum-s3-iam

Yum package manager plugin for private S3 repositories. Uses Amazon IAM & EC2 Roles.
Apache License 2.0
162 stars 99 forks source link

CertificateError for bucket name with dots #47

Closed sanyer closed 8 years ago

sanyer commented 8 years ago

Using a bucket which name includes dots raises Certificate Error:

Loaded plugins: priorities, s3iam, update-motd, upgrade-helper
Traceback (most recent call last):
  File "/usr/bin/yum", line 29, in <module>
    yummain.user_main(sys.argv[1:], exit_code=True)
  File "/usr/share/yum-cli/yummain.py", line 367, in user_main
    errcode = main(args)
  File "/usr/share/yum-cli/yummain.py", line 174, in main
    result, resultmsgs = base.doCommands()
  File "/usr/share/yum-cli/cli.py", line 572, in doCommands
    return self.yum_cli_commands[self.basecmd].doCommand(self, self.basecmd, self.extcmds)
  File "/usr/share/yum-cli/yumcommands.py", line 1728, in doCommand
    return base.search(extcmds)
  File "/usr/share/yum-cli/cli.py", line 1441, in search
    for (po, keys, matched_value) in matching:
  File "/usr/lib/python2.7/dist-packages/yum/__init__.py", line 3176, in searchGenerator
    for sack in self.pkgSack.sacks.values():
  File "/usr/lib/python2.7/dist-packages/yum/__init__.py", line 1077, in <lambda>
    pkgSack = property(fget=lambda self: self._getSacks(),
  File "/usr/lib/python2.7/dist-packages/yum/__init__.py", line 782, in _getSacks
    self.repos.populateSack(which=repos)
  File "/usr/lib/python2.7/dist-packages/yum/repos.py", line 383, in populateSack
    sack.populate(repo, mdtype, callback, cacheonly)
  File "/usr/lib/python2.7/dist-packages/yum/yumRepo.py", line 250, in populate
    if self._check_db_version(repo, mydbtype):
  File "/usr/lib/python2.7/dist-packages/yum/yumRepo.py", line 342, in _check_db_version
    return repo._check_db_version(mdtype)
  File "/usr/lib/python2.7/dist-packages/yum/yumRepo.py", line 1520, in _check_db_version
    repoXML = self.repoXML
  File "/usr/lib/python2.7/dist-packages/yum/yumRepo.py", line 1706, in <lambda>
    repoXML = property(fget=lambda self: self._getRepoXML(),
  File "/usr/lib/python2.7/dist-packages/yum/yumRepo.py", line 1702, in _getRepoXML
    self._loadRepoXML(text=self.ui_id)
  File "/usr/lib/python2.7/dist-packages/yum/yumRepo.py", line 1693, in _loadRepoXML
    return self._groupLoadRepoXML(text, self._mdpolicy2mdtypes())
  File "/usr/lib/python2.7/dist-packages/yum/yumRepo.py", line 1667, in _groupLoadRepoXML
    if self._commonLoadRepoXML(text):
  File "/usr/lib/python2.7/dist-packages/yum/yumRepo.py", line 1492, in _commonLoadRepoXML
    result = self._getFileRepoXML(local, text)
  File "/usr/lib/python2.7/dist-packages/yum/yumRepo.py", line 1270, in _getFileRepoXML
    size=102400) # setting max size as 100K
  File "/usr/lib/python2.7/dist-packages/yum/yumRepo.py", line 1058, in _getFile
    **kwargs
  File "/usr/lib/yum-plugins/s3iam.py", line 302, in urlgrab
    response = urllib2.urlopen(request)
  File "/usr/lib64/python2.7/urllib2.py", line 154, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib64/python2.7/urllib2.py", line 431, in open
    response = self._open(req, data)
  File "/usr/lib64/python2.7/urllib2.py", line 449, in _open
    '_open', req)
  File "/usr/lib64/python2.7/urllib2.py", line 409, in _call_chain
    result = func(*args)
  File "/usr/lib64/python2.7/urllib2.py", line 1242, in https_open
    context=self._context)
  File "/usr/lib64/python2.7/urllib2.py", line 1196, in do_open
    h.request(req.get_method(), req.get_selector(), req.data, headers)
  File "/usr/lib64/python2.7/httplib.py", line 1053, in request
    self._send_request(method, url, body, headers)
  File "/usr/lib64/python2.7/httplib.py", line 1093, in _send_request
    self.endheaders(body)
  File "/usr/lib64/python2.7/httplib.py", line 1049, in endheaders
    self._send_output(message_body)
  File "/usr/lib64/python2.7/httplib.py", line 893, in _send_output
    self.send(msg)
  File "/usr/lib64/python2.7/httplib.py", line 855, in send
    self.connect()
  File "/usr/lib64/python2.7/httplib.py", line 1274, in connect
    server_hostname=server_hostname)
  File "/usr/lib64/python2.7/ssl.py", line 352, in wrap_socket
    _context=self)
  File "/usr/lib64/python2.7/ssl.py", line 579, in __init__
    self.do_handshake()
  File "/usr/lib64/python2.7/ssl.py", line 816, in do_handshake
    match_hostname(self.getpeercert(), self.server_hostname)
  File "/usr/lib64/python2.7/ssl.py", line 271, in match_hostname
    % (hostname, ', '.join(map(repr, dnsnames))))
ssl.CertificateError: hostname 'repo.trv.ams.s3.amazonaws.com' doesn't match either of '*.s3.amazonaws.com', 's3.amazonaws.com'

Same happened for boto some time ago: https://github.com/boto/boto/issues/2836 Simplest way to fix it is monkey patching ssl:

# https://github.com/boto/boto/issues/2836#issuecomment-68608362
import ssl
if hasattr(ssl, '_create_unverified_context'):
   ssl._create_default_https_context = ssl._create_unverified_context

or

# https://github.com/boto/boto/issues/2836#issuecomment-68682573
import ssl

_old_match_hostname = ssl.match_hostname

def _new_match_hostname(cert, hostname):
   if hostname.endswith('.s3.amazonaws.com'):
      pos = hostname.find('.s3.amazonaws.com')
      hostname = hostname[:pos].replace('.', '') + hostname[pos:]
   return _old_match_hostname(cert, hostname)

ssl.match_hostname = _new_match_hostname

I've made a pull request here https://github.com/seporaitis/yum-s3-iam/pull/46

mbrossard commented 8 years ago

Try using the following syntax:

sanyer commented 8 years ago

@mbrossard oops, I've missed notification about your comment somehow. Will test suggested syntax today, thanks.

sanyer commented 8 years ago

Nice, https://s3-<region>.amazonaws.com/<bucket>/<path> worked for me nicely. Wow, I lost a lot of time on this issue, including reading AWS docs, but didn't really notice path-style URL possibility for S3 buckets. Thanks for pointing that out ;-)

So, this issue could be avoided just by using path-style URL. Could be added to description, though.