Beispiel #1
0
    def __call__(self, req):
        if req.path == '/info':
            # Ensure /info requests get the freshest results
            self.register_info()
            return self.app

        try:
            (version, acc, cont, obj) = req.split_path(3, 4, True)
            bad_path = False
        except ValueError:
            bad_path = True

        # use of bad_path bool is to avoid recursive tracebacks
        if bad_path or not valid_api_version(version):
            return self.app

        # validate container-sync metdata update
        info = get_container_info(req.environ, self.app, swift_source='CS')
        sync_to = req.headers.get('x-container-sync-to')
        if req.method in ('PUT', 'POST') and cont and not obj:
            versions_cont = info.get('sysmeta', {}).get('versions-container')
            if sync_to and versions_cont:
                raise HTTPBadRequest(
                    'Cannot configure container sync on a container '
                    'with object versioning configured.',
                    request=req)

        if not self.allow_full_urls:
            if sync_to and not sync_to.startswith('//'):
                raise HTTPBadRequest(
                    body='Full URLs are not allowed for X-Container-Sync-To '
                    'values. Only realm values of the format '
                    '//realm/cluster/account/container are allowed.\n',
                    request=req)
        auth = req.headers.get('x-container-sync-auth')
        if auth:
            valid = False
            auth = auth.split()
            if len(auth) != 3:
                req.environ.setdefault('swift.log_info',
                                       []).append('cs:not-3-args')
            else:
                realm, nonce, sig = auth
                realm_key = self.realms_conf.key(realm)
                realm_key2 = self.realms_conf.key2(realm)
                if not realm_key:
                    req.environ.setdefault('swift.log_info',
                                           []).append('cs:no-local-realm-key')
                else:
                    user_key = info.get('sync_key')
                    if not user_key:
                        req.environ.setdefault(
                            'swift.log_info',
                            []).append('cs:no-local-user-key')
                    else:
                        # x-timestamp headers get shunted by gatekeeper
                        if 'x-backend-inbound-x-timestamp' in req.headers:
                            req.headers['x-timestamp'] = req.headers.pop(
                                'x-backend-inbound-x-timestamp')

                        expected = self.realms_conf.get_sig(
                            req.method, req.path,
                            req.headers.get('x-timestamp', '0'), nonce,
                            realm_key, user_key)
                        expected2 = self.realms_conf.get_sig(
                            req.method, req.path,
                            req.headers.get('x-timestamp', '0'), nonce,
                            realm_key2, user_key) if realm_key2 else expected
                        if not streq_const_time(sig, expected) and \
                                not streq_const_time(sig, expected2):
                            req.environ.setdefault('swift.log_info',
                                                   []).append('cs:invalid-sig')
                        else:
                            req.environ.setdefault('swift.log_info',
                                                   []).append('cs:valid')
                            valid = True
            if not valid:
                exc = HTTPUnauthorized(
                    body='X-Container-Sync-Auth header not valid; '
                    'contact cluster operator for support.',
                    headers={'content-type': 'text/plain'},
                    request=req)
                exc.headers['www-authenticate'] = ' '.join([
                    'SwiftContainerSync',
                    exc.www_authenticate().split(None, 1)[1]
                ])
                raise exc
            else:
                req.environ['swift.authorize_override'] = True
                # An SLO manifest will already be in the internal manifest
                # syntax and might be synced before its segments, so stop SLO
                # middleware from performing the usual manifest validation.
                req.environ['swift.slo_override'] = True
                # Similar arguments for static symlinks
                req.environ['swift.symlink_override'] = True

        return self.app
Beispiel #2
0
 def __call__(self, req):
     if not self.allow_full_urls:
         sync_to = req.headers.get('x-container-sync-to')
         if sync_to and not sync_to.startswith('//'):
             raise HTTPBadRequest(
                 body='Full URLs are not allowed for X-Container-Sync-To '
                 'values. Only realm values of the format '
                 '//realm/cluster/account/container are allowed.\n',
                 request=req)
     auth = req.headers.get('x-container-sync-auth')
     if auth:
         valid = False
         auth = auth.split()
         if len(auth) != 3:
             req.environ.setdefault('swift.log_info',
                                    []).append('cs:not-3-args')
         else:
             realm, nonce, sig = auth
             realm_key = self.realms_conf.key(realm)
             realm_key2 = self.realms_conf.key2(realm)
             if not realm_key:
                 req.environ.setdefault('swift.log_info',
                                        []).append('cs:no-local-realm-key')
             else:
                 info = get_container_info(req.environ,
                                           self.app,
                                           swift_source='CS')
                 user_key = info.get('sync_key')
                 if not user_key:
                     req.environ.setdefault(
                         'swift.log_info',
                         []).append('cs:no-local-user-key')
                 else:
                     expected = self.realms_conf.get_sig(
                         req.method, req.path,
                         req.headers.get('x-timestamp', '0'), nonce,
                         realm_key, user_key)
                     expected2 = self.realms_conf.get_sig(
                         req.method, req.path,
                         req.headers.get('x-timestamp', '0'), nonce,
                         realm_key2, user_key) if realm_key2 else expected
                     if not streq_const_time(sig, expected) and \
                             not streq_const_time(sig, expected2):
                         req.environ.setdefault('swift.log_info',
                                                []).append('cs:invalid-sig')
                     else:
                         req.environ.setdefault('swift.log_info',
                                                []).append('cs:valid')
                         valid = True
         if not valid:
             exc = HTTPUnauthorized(
                 body='X-Container-Sync-Auth header not valid; '
                 'contact cluster operator for support.',
                 headers={'content-type': 'text/plain'},
                 request=req)
             exc.headers['www-authenticate'] = ' '.join([
                 'SwiftContainerSync',
                 exc.www_authenticate().split(None, 1)[1]
             ])
             raise exc
         else:
             req.environ['swift.authorize_override'] = True
     if req.path == '/info':
         # Ensure /info requests get the freshest results
         dct = {}
         for realm in self.realms_conf.realms():
             clusters = self.realms_conf.clusters(realm)
             if clusters:
                 dct[realm] = {'clusters': dict((c, {}) for c in clusters)}
         register_swift_info('container_sync', realms=dct)
     return self.app
Beispiel #3
0
    def __call__(self, req):
        if not self.allow_full_urls:
            sync_to = req.headers.get('x-container-sync-to')
            if sync_to and not sync_to.startswith('//'):
                raise HTTPBadRequest(
                    body='Full URLs are not allowed for X-Container-Sync-To '
                         'values. Only realm values of the format '
                         '//realm/cluster/account/container are allowed.\n',
                    request=req)
        auth = req.headers.get('x-container-sync-auth')
        if auth:
            valid = False
            auth = auth.split()
            if len(auth) != 3:
                req.environ.setdefault('swift.log_info', []).append(
                    'cs:not-3-args')
            else:
                realm, nonce, sig = auth
                realm_key = self.realms_conf.key(realm)
                realm_key2 = self.realms_conf.key2(realm)
                if not realm_key:
                    req.environ.setdefault('swift.log_info', []).append(
                        'cs:no-local-realm-key')
                else:
                    info = get_container_info(
                        req.environ, self.app, swift_source='CS')
                    user_key = info.get('sync_key')
                    if not user_key:
                        req.environ.setdefault('swift.log_info', []).append(
                            'cs:no-local-user-key')
                    else:
                        # x-timestamp headers get shunted by gatekeeper
                        if 'x-backend-inbound-x-timestamp' in req.headers:
                            req.headers['x-timestamp'] = req.headers.pop(
                                'x-backend-inbound-x-timestamp')

                        expected = self.realms_conf.get_sig(
                            req.method, req.path,
                            req.headers.get('x-timestamp', '0'), nonce,
                            realm_key, user_key)
                        expected2 = self.realms_conf.get_sig(
                            req.method, req.path,
                            req.headers.get('x-timestamp', '0'), nonce,
                            realm_key2, user_key) if realm_key2 else expected
                        if not streq_const_time(sig, expected) and \
                                not streq_const_time(sig, expected2):
                            req.environ.setdefault(
                                'swift.log_info', []).append('cs:invalid-sig')
                        else:
                            req.environ.setdefault(
                                'swift.log_info', []).append('cs:valid')
                            valid = True
            if not valid:
                exc = HTTPUnauthorized(
                    body='X-Container-Sync-Auth header not valid; '
                         'contact cluster operator for support.',
                    headers={'content-type': 'text/plain'},
                    request=req)
                exc.headers['www-authenticate'] = ' '.join([
                    'SwiftContainerSync',
                    exc.www_authenticate().split(None, 1)[1]])
                raise exc
            else:
                req.environ['swift.authorize_override'] = True
                # An SLO manifest will already be in the internal manifest
                # syntax and might be synced before its segments, so stop SLO
                # middleware from performing the usual manifest validation.
                req.environ['swift.slo_override'] = True

        if req.path == '/info':
            # Ensure /info requests get the freshest results
            self.register_info()
        return self.app
Beispiel #4
0
 def __call__(self, req):
     if not self.allow_full_urls:
         sync_to = req.headers.get('x-container-sync-to')
         if sync_to and not sync_to.startswith('//'):
             raise HTTPBadRequest(
                 body='Full URLs are not allowed for X-Container-Sync-To '
                      'values. Only realm values of the format '
                      '//realm/cluster/account/container are allowed.\n',
                 request=req)
     auth = req.headers.get('x-container-sync-auth')
     if auth:
         valid = False
         auth = auth.split()
         if len(auth) != 3:
             req.environ.setdefault('swift.log_info', []).append(
                 'cs:not-3-args')
         else:
             realm, nonce, sig = auth
             realm_key = self.realms_conf.key(realm)
             realm_key2 = self.realms_conf.key2(realm)
             if not realm_key:
                 req.environ.setdefault('swift.log_info', []).append(
                     'cs:no-local-realm-key')
             else:
                 info = get_container_info(
                     req.environ, self.app, swift_source='CS')
                 user_key = info.get('sync_key')
                 if not user_key:
                     req.environ.setdefault('swift.log_info', []).append(
                         'cs:no-local-user-key')
                 else:
                     expected = self.realms_conf.get_sig(
                         req.method, req.path,
                         req.headers.get('x-timestamp', '0'), nonce,
                         realm_key, user_key)
                     expected2 = self.realms_conf.get_sig(
                         req.method, req.path,
                         req.headers.get('x-timestamp', '0'), nonce,
                         realm_key2, user_key) if realm_key2 else expected
                     if not streq_const_time(sig, expected) and \
                             not streq_const_time(sig, expected2):
                         req.environ.setdefault(
                             'swift.log_info', []).append('cs:invalid-sig')
                     else:
                         req.environ.setdefault(
                             'swift.log_info', []).append('cs:valid')
                         valid = True
         if not valid:
             exc = HTTPUnauthorized(
                 body='X-Container-Sync-Auth header not valid; '
                      'contact cluster operator for support.',
                 headers={'content-type': 'text/plain'},
                 request=req)
             exc.headers['www-authenticate'] = ' '.join([
                 'SwiftContainerSync',
                 exc.www_authenticate().split(None, 1)[1]])
             raise exc
         else:
             req.environ['swift.authorize_override'] = True
     if req.path == '/info':
         # Ensure /info requests get the freshest results
         dct = {}
         for realm in self.realms_conf.realms():
             clusters = self.realms_conf.clusters(realm)
             if clusters:
                 dct[realm] = {'clusters': dict((c, {}) for c in clusters)}
         register_swift_info('container_sync', realms=dct)
     return self.app
Beispiel #5
0
    def __call__(self, req):
        if not self.allow_full_urls:
            sync_to = req.headers.get('x-container-sync-to')
            if sync_to and not sync_to.startswith('//'):
                raise HTTPBadRequest(
                    body='Full URLs are not allowed for X-Container-Sync-To '
                    'values. Only realm values of the format '
                    '//realm/cluster/account/container are allowed.\n',
                    request=req)
        auth = req.headers.get('x-container-sync-auth')
        if auth:
            valid = False
            auth = auth.split()
            if len(auth) != 3:
                req.environ.setdefault('swift.log_info',
                                       []).append('cs:not-3-args')
            else:
                realm, nonce, sig = auth
                realm_key = self.realms_conf.key(realm)
                realm_key2 = self.realms_conf.key2(realm)
                if not realm_key:
                    req.environ.setdefault('swift.log_info',
                                           []).append('cs:no-local-realm-key')
                else:
                    info = get_container_info(req.environ,
                                              self.app,
                                              swift_source='CS')
                    user_key = info.get('sync_key')
                    if not user_key:
                        req.environ.setdefault(
                            'swift.log_info',
                            []).append('cs:no-local-user-key')
                    else:
                        # x-timestamp headers get shunted by gatekeeper
                        if 'x-backend-inbound-x-timestamp' in req.headers:
                            req.headers['x-timestamp'] = req.headers.pop(
                                'x-backend-inbound-x-timestamp')

                        expected = self.realms_conf.get_sig(
                            req.method, req.path,
                            req.headers.get('x-timestamp', '0'), nonce,
                            realm_key, user_key)
                        expected2 = self.realms_conf.get_sig(
                            req.method, req.path,
                            req.headers.get('x-timestamp', '0'), nonce,
                            realm_key2, user_key) if realm_key2 else expected
                        if not streq_const_time(sig, expected) and \
                                not streq_const_time(sig, expected2):
                            req.environ.setdefault('swift.log_info',
                                                   []).append('cs:invalid-sig')
                        else:
                            req.environ.setdefault('swift.log_info',
                                                   []).append('cs:valid')
                            valid = True
            if not valid:
                exc = HTTPUnauthorized(
                    body='X-Container-Sync-Auth header not valid; '
                    'contact cluster operator for support.',
                    headers={'content-type': 'text/plain'},
                    request=req)
                exc.headers['www-authenticate'] = ' '.join([
                    'SwiftContainerSync',
                    exc.www_authenticate().split(None, 1)[1]
                ])
                raise exc
            else:
                req.environ['swift.authorize_override'] = True
                # An SLO manifest will already be in the internal manifest
                # syntax and might be synced before its segments, so stop SLO
                # middleware from performing the usual manifest validation.
                req.environ['swift.slo_override'] = True

        if req.path == '/info':
            # Ensure /info requests get the freshest results
            self.register_info()
        return self.app