Ejemplo n.º 1
0
  def testDoAnyAuth(self):
    """Test DoAnyAuth()."""

    email = '*****@*****.**'
    require_level = 123

    with mock.patch.object(auth, 'DoUserAuth', return_value=email) as m:
      self.assertEqual(auth.DoAnyAuth(is_admin=True), email)
      m.assert_called_once_with(is_admin=True)

    with mock.patch.object(
        auth, 'DoUserAuth', side_effect=auth.IsAdminMismatch):
      self.assertRaises(auth.IsAdminMismatch, auth.DoAnyAuth, is_admin=True)

    with mock.patch.object(
        auth, 'DoUserAuth', side_effect=auth.NotAuthenticated):
      with mock.patch.object(
          auth.gaeserver, 'DoMunkiAuth', return_value='user') as m:
        self.assertEqual(auth.DoAnyAuth(
            is_admin=True, require_level=require_level), 'user')
        m.assert_called_once_with(require_level=require_level)

    with mock.patch.object(
        auth, 'DoUserAuth', side_effect=auth.NotAuthenticated):
      with mock.patch.object(
          auth.gaeserver, 'DoMunkiAuth',
          side_effect=auth.gaeserver.NotAuthenticated):
        self.assertRaises(
            auth.base.NotAuthenticated,
            auth.DoAnyAuth, is_admin=True, require_level=require_level)
Ejemplo n.º 2
0
    def MockDoAnyAuth(self, fail=False, and_return=None):
        """Mock calling auth.DoAnyAuth().

    Args:
      fail: bool, whether to fail or not
      and_return: any, variable to pass to AndReturn, default None
    """
        if 'authDoAnyAuth' not in self._set_mock:
            self.mox.StubOutWithMock(auth, 'DoAnyAuth')
            self._set_mock['authDoAnyAuth'] = 1
        if fail:
            auth.DoAnyAuth().AndRaise(auth.NotAuthenticated)
        else:
            auth.DoAnyAuth().AndReturn(and_return)
Ejemplo n.º 3
0
    def get(self, name):
        """Catalog get handler.

    Args:
      name: string catalog name to get.

    Returns:
      A webapp.Response() response.
    """
        auth.DoAnyAuth()

        catalog = models.Catalog.MemcacheWrappedGet(name)
        if not catalog:
            self.response.set_status(httplib.NOT_FOUND)
            return

        header_date_str = self.request.headers.get('If-Modified-Since', '')
        if not handlers.IsClientResourceExpired(catalog.mtime,
                                                header_date_str):
            self.response.set_status(httplib.NOT_MODIFIED)
            return

        self.response.headers['Last-Modified'] = catalog.mtime.strftime(
            handlers.HEADER_DATE_FORMAT)

        self.response.headers['Content-Type'] = 'text/xml; charset=utf-8'
        self.response.out.write(catalog.plist_xml)
Ejemplo n.º 4
0
  def get(self, client_id_str=''):
    """AppleSUS get handler.

    Args:
      name: str, optional, catalog name to get.
    """
    session = auth.DoAnyAuth()
    client_id = handlers.GetClientIdForRequest(
            self.request, session=session, client_id_str=client_id_str)

    # get only major.minor os_version, stripping miniscule versioning.
    # i.e. 10.6.6 becomes 10.6, 10.23.6.x.x becomes 10.23
    full_os_version = client_id.get('os_version', '') or ''
    os_version = '.'.join(full_os_version.split('.', 2)[:2])
    track = client_id.get('track', 'stable')
    catalog_name = '%s_%s' % (os_version, track)

    catalog = models.AppleSUSCatalog.MemcacheWrappedGet(catalog_name)
    if not catalog:
      logging.warning('Apple SUS catalog not found: %s', catalog_name)
      self.response.set_status(404)
      return

    header_date_str = self.request.headers.get('If-Modified-Since', '')
    catalog_date = catalog.mtime
    if handlers.IsClientResourceExpired(catalog_date, header_date_str):
      self.response.headers['Last-Modified'] = catalog_date.strftime(
          handlers.HEADER_DATE_FORMAT)
      self.response.headers['Content-Type'] = 'text/xml; charset=utf-8'
      self.response.out.write(catalog.plist)
    else:
      self.response.set_status(304)
Ejemplo n.º 5
0
    def testDoAnyAuth(self):
        """Test DoAnyAuth()."""

        is_admin = True
        require_level = 123

        self.mox.StubOutWithMock(auth, 'DoUserAuth')
        self.mox.StubOutWithMock(auth.gaeserver, 'DoMunkiAuth')

        auth.DoUserAuth(is_admin=is_admin).AndReturn('user')

        auth.DoUserAuth(is_admin=is_admin).AndRaise(auth.IsAdminMismatch)

        auth.DoUserAuth(is_admin=is_admin).AndRaise(auth.NotAuthenticated)
        auth.gaeserver.DoMunkiAuth(
            require_level=require_level).AndReturn('token')

        auth.DoUserAuth(is_admin=is_admin).AndRaise(auth.NotAuthenticated)
        auth.gaeserver.DoMunkiAuth(require_level=require_level).AndRaise(
            auth.gaeserver.NotAuthenticated)

        self.mox.ReplayAll()

        self.assertEqual(auth.DoAnyAuth(is_admin=is_admin), 'user')

        self.assertRaises(auth.IsAdminMismatch,
                          auth.DoAnyAuth,
                          is_admin=is_admin)

        self.assertEqual(
            auth.DoAnyAuth(is_admin=is_admin, require_level=require_level),
            'token')

        self.assertRaises(auth.base.NotAuthenticated,
                          auth.DoAnyAuth,
                          is_admin=is_admin,
                          require_level=require_level)

        self.mox.VerifyAll()
Ejemplo n.º 6
0
  def get(self, name):
    """Catalog get handler.

    Args:
      name: string catalog name to get.

    Returns:
      A webapp.Response() response.
    """
    auth.DoAnyAuth()
    catalog = models.Catalog.MemcacheWrappedGet(name, 'plist_xml')
    if catalog:
      self.response.headers['Content-Type'] = 'text/xml; charset=utf-8'
      self.response.out.write(catalog)
    else:
      self.response.set_status(404)
Ejemplo n.º 7
0
    def get(self, name):
        auth.DoAnyAuth()
        try:
            bucket = settings.ICONS_GCS_BUCKET
        except AttributeError:
            logging.warning('Dedicated icons GCS bucket is not set.')
            self.abort(httplib.BAD_REQUEST)

        name = name.split('.')[0]
        icon_path = '/%s/%s.png' % (bucket, base64.urlsafe_b64encode(name))

        try:
            with gcs.open(icon_path, 'r') as gcs_file:
                self.response.headers['Content-Type'] = 'image/png'
                self.response.write(gcs_file.read())
        except gcs.NotFoundError:
            self.abort(httplib.NOT_FOUND)
Ejemplo n.º 8
0
    def get(self, client_id_str=''):
        """Manifest get handler.

    Args:
      client_id: optional str client_id; only needed for user requests.

    Returns:
      A webapp.Response() response.
    """
        session = auth.DoAnyAuth()
        client_id = handlers.GetClientIdForRequest(self.request,
                                                   session=session,
                                                   client_id_str=client_id_str)

        try:
            plist_xml = common.GetComputerManifest(client_id=client_id,
                                                   packagemap=False)
        except common.ManifestNotFoundError, e:
            logging.warning('Invalid manifest requested: %s', str(e))
            self.response.set_status(404)
            return
Ejemplo n.º 9
0
    def get(self, name):
        auth.DoAnyAuth()

        if name == '_icon_hashes.plist':
            # munki 3.1 starts reading hashes from special plist.
            # to avoid 404 spam in logs, replying with 200.
            return

        try:
            bucket = settings.ICONS_GCS_BUCKET
        except AttributeError:
            logging.warning('Dedicated icons GCS bucket is not set.')
            self.abort(httplib.BAD_REQUEST)

        name = name.split('.')[0]
        icon_path = '/%s/%s.png' % (bucket, base64.urlsafe_b64encode(name))

        try:
            with gcs.open(icon_path, 'r') as gcs_file:
                self.response.headers['Content-Type'] = 'image/png'
                self.response.write(gcs_file.read())
        except gcs.NotFoundError:
            self.abort(httplib.NOT_FOUND)
Ejemplo n.º 10
0
  def get(self, client_id_str=''):
    """GET

    Returns:
      None if a blob is being returned,
      or a response object
    """
    session = auth.DoAnyAuth()
    client_id = handlers.GetClientIdForRequest(
        self.request, session=session, client_id_str=client_id_str)

    logging.info('Repair client ID: %s', client_id)
    filename = None
    for pkg in models.PackageInfo.all().filter('name =', 'munkitools'):
      if client_id.get('track', '') in pkg.catalogs:
        filename = pkg.filename
        break

    if filename:
      logging.info('Sending client: %s', filename)
      super(ClientRepair, self).get(filename)
    else:
      logging.warning('No repair client found.')
Ejemplo n.º 11
0
Archivo: pkgs.py Proyecto: smusa/simian
    def get(self, filename):
        """GET

    Args:
      filename: str, package filename like 'foo.dmg'
    Returns:
      None if a blob is being returned,
      or a response object
    """
        auth_return = auth.DoAnyAuth()
        if hasattr(auth_return, 'email'):
            email = auth_return.email()
            if not auth.IsAdminUser(email) and not auth.IsSupportUser(email):
                raise auth.IsAdminMismatch

        filename = urllib.unquote(filename)
        pkg = models.PackageInfo.MemcacheWrappedGet(filename)

        if pkg is None or not pkg.blobstore_key:
            self.error(404)
            return

        if common.IsPanicModeNoPackages():
            self.error(503)
            return

        # Get the Blobstore BlobInfo for this package; memcache wrapped.
        memcache_key = 'blobinfo_%s' % filename
        blob_info = memcache.get(memcache_key)
        if not blob_info:
            blob_info = blobstore.BlobInfo.get(pkg.blobstore_key)
            if blob_info:
                memcache.set(memcache_key, blob_info,
                             300)  # cache for 5 minutes.
            else:
                logging.critical(
                    'Failure fetching BlobInfo for %s. Verify the blob exists: %s',
                    pkg.filename, pkg.blobstore_key)
                self.error(404)
                return

        header_date_str = self.request.headers.get('If-Modified-Since', '')
        etag_nomatch_str = self.request.headers.get('If-None-Match', 0)
        etag_match_str = self.request.headers.get('If-Match', 0)
        pkg_date = blob_info.creation
        pkg_size_bytes = blob_info.size

        # TODO(user): The below can be simplified once all of our clients
        # have ETag values set on the filesystem for these files.  The
        # parsing of If-Modified-Since could be removed.  Removing it prematurely
        # will cause a re-download of all packages on all clients for 1 iteration
        # until they all have ETag values.

        # Reduce complexity of elif conditional below.
        # If an If-None-Match: ETag is supplied, don't worry about a
        # missing file modification date -- the ETag supplies everything needed.
        if etag_nomatch_str and not header_date_str:
            resource_expired = False
        else:
            resource_expired = handlers.IsClientResourceExpired(
                pkg_date, header_date_str)

        # Client supplied If-Match: etag, but that etag does not match current
        # etag.  return 412.
        if (etag_match_str and pkg.pkgdata_sha256
                and etag_match_str != pkg.pkgdata_sha256):
            self.response.set_status(412)

        # Client supplied no etag or If-No-Match: etag, and the etag did not
        # match, or the client's file is older than the mod time of this package.
        elif ((etag_nomatch_str and pkg.pkgdata_sha256
               and etag_nomatch_str != pkg.pkgdata_sha256)
              or resource_expired):
            self.response.headers['Content-Disposition'] = str(
                'attachment; filename=%s' % filename)
            # header date empty or package has changed, send blob with last-mod date.
            if pkg.pkgdata_sha256:
                self.response.headers['ETag'] = str(pkg.pkgdata_sha256)
            self.response.headers['Last-Modified'] = pkg_date.strftime(
                handlers.HEADER_DATE_FORMAT)
            self.response.headers['X-Download-Size'] = str(pkg_size_bytes)
            self.send_blob(pkg.blobstore_key)
        else:
            # Client doesn't need to do anything, current version is OK based on
            # ETag and/or last modified date.
            if pkg.pkgdata_sha256:
                self.response.headers['ETag'] = str(pkg.pkgdata_sha256)
            self.response.set_status(304)
Ejemplo n.º 12
0
    def get(self, filename=None):
        """GET

    Args:
      filename: string like Firefox-1.0.dmg
    """
        auth_return = auth.DoAnyAuth()
        if hasattr(auth_return, 'email'):
            email = auth_return.email()
            if not any((
                    auth.IsAdminUser(email),
                    auth.IsSupportUser(email),
            )):
                raise auth.IsAdminMismatch

        if filename:
            filename = urllib.unquote(filename)
            hash_str = self.request.get('hash')

            if hash_str:
                lock = models.GetLockForPackage(filename)
                try:
                    lock.Acquire(timeout=30, max_acquire_attempts=5)
                except datastore_locks.AcquireLockError:
                    self.response.set_status(httplib.FORBIDDEN)
                    self.response.out.write('Could not lock pkgsinfo')
                    return

            pkginfo = models.PackageInfo.get_by_key_name(filename)
            if pkginfo:
                self.response.headers[
                    'Content-Type'] = 'text/xml; charset=utf-8'
                if hash_str:
                    self.response.headers['X-Pkgsinfo-Hash'] = self._Hash(
                        pkginfo.plist)
                self.response.out.write(pkginfo.plist)
            else:
                if hash_str:
                    lock.Release()
                self.response.set_status(httplib.NOT_FOUND)
                return

            if hash_str:
                lock.Release()
        else:
            query = models.PackageInfo.all()

            filename = self.request.get('filename')
            if filename:
                query.filter('filename', filename)

            install_types = self.request.get_all('install_types')
            for install_type in install_types:
                query.filter('install_types =', install_type)

            catalogs = self.request.get_all('catalogs')
            for catalog in catalogs:
                query.filter('catalogs =', catalog)

            pkgs = []
            for p in query:
                pkg = {}
                for k in p.properties():
                    if k != '_plist':
                        pkg[k] = getattr(p, k)
                pkgs.append(pkg)
            self.response.out.write('<?xml version="1.0" encoding="UTF-8"?>\n')
            self.response.out.write(plist.GetXmlStr(pkgs))
            self.response.headers['Content-Type'] = 'text/xml; charset=utf-8'
Ejemplo n.º 13
0
    def get(self, filename=None):
        """GET

    Args:
      filename: string like Firefox-1.0.dmg
    """
        auth_return = auth.DoAnyAuth()
        if hasattr(auth_return, 'email'):
            email = auth_return.email()
            if not any((
                    auth.IsAdminUser(email),
                    auth.IsSupportUser(email),
            )):
                raise auth.IsAdminMismatch

        if filename:
            filename = urllib.unquote(filename)
            hash_str = self.request.get('hash')

            if hash_str:
                lock = 'pkgsinfo_%s' % filename
                if not gae_util.ObtainLock(lock, timeout=5.0):
                    self.response.set_status(403)
                    self.response.out.write('Could not lock pkgsinfo')
                    return

            pkginfo = models.PackageInfo.get_by_key_name(filename)
            if pkginfo:
                self.response.headers[
                    'Content-Type'] = 'text/xml; charset=utf-8'
                if hash_str:
                    self.response.headers['X-Pkgsinfo-Hash'] = self._Hash(
                        pkginfo.plist)
                self.response.out.write(pkginfo.plist)
            else:
                if hash_str:
                    gae_util.ReleaseLock(lock)
                self.response.set_status(404)
                return

            if hash_str:
                gae_util.ReleaseLock(lock)
        else:
            query = models.PackageInfo.all()

            filename = self.request.get('filename')
            if filename:
                query.filter('filename', filename)

            install_types = self.request.get_all('install_types')
            for install_type in install_types:
                query.filter('install_types =', install_type)

            catalogs = self.request.get_all('catalogs')
            for catalog in catalogs:
                query.filter('catalogs =', catalog)

            pkgs = []
            for p in query:
                pkg = {}
                for k in p.properties():
                    if k != '_plist':
                        pkg[k] = getattr(p, k)
                pkgs.append(pkg)
            self.response.out.write('<?xml version="1.0" encoding="UTF-8"?>\n')
            self.response.out.write(plist.GetXmlStr(pkgs))
            self.response.headers['Content-Type'] = 'text/xml; charset=utf-8'