Ejemplo n.º 1
0
    def IsKeyRotationNeeded(self, target_id, tag='default'):
        """Check whether a key rotation is required.

    Args:
      target_id: str, Target ID.
      tag: str, passphrase tag.
    Raises:
      RequestError: there was an error getting status from server.
    Returns:
      bool: True if a key rotation is required.
    """
        url = '%s?%s' % (util.JoinURL(
            self.base_url, '/api/v1/rekey-required/', self.ESCROW_PATH,
            target_id), urllib.urlencode({'tag': tag}))
        request = fancy_urllib.FancyRequest(url)
        request.set_ssl_info(ca_certs=self._ca_certs_file)
        try:
            response = self.opener.open(request)
        except urllib2.URLError as e:  # Parent of urllib2.HTTPError.
            if isinstance(e, urllib2.HTTPError):
                e.msg += ': ' + e.read()
            raise RequestError('Failed to get status. %s' % e)
        content = response.read()
        if not content.startswith(JSON_PREFIX):
            raise RequestError('Expected JSON prefix missing.')
        return json.loads(content[len(JSON_PREFIX):])
Ejemplo n.º 2
0
    def RetrieveSecret(self, target_id):
        """Fetches and returns the passphrase.

    Args:
      target_id: str, Target ID to fetch the passphrase for.
    Returns:
      str: passphrase.
    Raises:
      RequestError: there was an error downloading the passphrase.
      NotFoundError: no passphrase was found for the given target_id.
    """
        xsrf_token = self._FetchXsrfToken(base_settings.GET_PASSPHRASE_ACTION)
        url = '%s?%s' % (util.JoinURL(self.escrow_url,
                                      urllib.quote(target_id)),
                         urllib.urlencode({'xsrf-token': xsrf_token}))
        request = fancy_urllib.FancyRequest(url)
        request.set_ssl_info(ca_certs=self._ca_certs_file)
        try:
            response = self.opener.open(request)
        except urllib2.URLError as e:  # Parent of urllib2.HTTPError.
            if isinstance(e, urllib2.HTTPError):
                e.msg += ': ' + e.read()
                if e.code == httplib.NOT_FOUND:
                    raise NotFoundError('Failed to retrieve passphrase. %s' %
                                        e)
            raise RequestError('Failed to retrieve passphrase. %s' % e)
        content = response.read()
        if not content.startswith(JSON_PREFIX):
            raise RequestError('Expected JSON prefix missing.')
        data = json.loads(content[len(JSON_PREFIX):])
        return data[self.PASSPHRASE_KEY]
Ejemplo n.º 3
0
 def _CreateRequest(self, url, data=None):
   """Creates a new urllib request."""
   req = fancy_urllib.FancyRequest(url, data=data)
   if self.host_override:
     req.add_header("Host", self.host_override)
   for key, value in self.extra_headers.iteritems():
     req.add_header(key, value)
   return req
Ejemplo n.º 4
0
def BuildClientLoginOpener(hostname, credentials):
  """Produce an urllib2 OpenerDirective that's logged in by client login.

  Args:
    hostname: host name for server
    credentials: A tuple of (email, password).

  Note: if necessary, "password" should be an application specific password.

  Returns:
    Tuple of (urllib2.OpenerDirective, cookielib.CookieJar) .
  Raises:
    AuthenticationError: when authentication fails.
  """
  cookiejar = cookielib.CookieJar()
  opener = urllib2.build_opener(
      urllib2.HTTPCookieProcessor(cookiejar),
      fancy_urllib.FancyHTTPSHandler(),
      fancy_urllib.FancyRedirectHandler())
  email, password = credentials

  # Step 1: We get an Auth token from ClientLogin.
  req = fancy_urllib.FancyRequest(
      'https://www.google.com/accounts/ClientLogin',
      urllib.urlencode({
          'accountType': 'HOSTED_OR_GOOGLE',
          'Email': email,
          'Passwd': password,
          'service': 'ah',
          'source': 'cauliflowervest',
          })
      )
  try:
    response = opener.open(req)
  except urllib2.HTTPError, e:
    error_body = e.read()
    # TODO(user): Consider more failure cases.
    if 'Error=BadAuthentication' in error_body:
      raise AuthenticationError('Bad email or password.')
    elif 'Error=CaptchaRequired' in error_body:
      # TODO(user): Provide a link to the page where users can fix this:
      #   https://www.google.com/accounts/DisplayUnlockCaptcha
      raise AuthenticationError(
          'Server responded with captcha request; captchas unsupported.')
    else:
      raise AuthenticationError('Authentication: Could not get service token.')
Ejemplo n.º 5
0
    def RetrievePassphrase(self, volume_uuid):
        """Fetches and returns the FileVault passphrase.

    Args:
      volume_uuid: str, Volume UUID to fetch the keychain for.
    Returns:
      str: passphrase to unlock the keychain.
    Raises:
      DownloadError: there was an error downloading the keychain.
    """
        request = fancy_urllib.FancyRequest(
            util.JoinURL(self.filevault_url, volume_uuid))
        request.set_ssl_info(ca_certs=self._ca_certs_file)
        try:
            response = self.opener.open(request)
        except urllib2.HTTPError, e:
            raise DownloadError('Failed to retrieve passphrase. %s' % str(e))
Ejemplo n.º 6
0
    def RetrieveSecret(self, volume_uuid):
        """Fetches and returns the passphrase.

    Args:
      volume_uuid: str, Volume UUID to fetch the passphrase for.
    Returns:
      str: passphrase to unlock an encrypted volume.
    Raises:
      RequestError: there was an error downloading the passphrase.
    """
        xsrf_token = self._FetchXsrfToken(base_settings.GET_PASSPHRASE_ACTION)
        url = '%s?%s' % (util.JoinURL(self.escrow_url, volume_uuid),
                         urllib.urlencode({'xsrf-token': xsrf_token}))
        request = fancy_urllib.FancyRequest(url)
        request.set_ssl_info(ca_certs=self._ca_certs_file)
        try:
            response = self.opener.open(request)
        except urllib2.HTTPError, e:
            raise RequestError('Failed to retrieve passphrase. %s' % str(e))
Ejemplo n.º 7
0
    def IsKeyRotationNeeded(self, target_id, tag='default'):
        """Check whether a key rotation is required.

    Args:
      target_id: str, Target ID.
      tag: str, passphrase tag.
    Raises:
      RequestError: there was an error getting status from server.
    Returns:
      bool: True if a key rotation is required.
    """
        url = '%s?%s' % (util.JoinURL(
            self.base_url, '/api/v1/rekey-required/', self.ESCROW_PATH,
            target_id), urllib.urlencode({'tag': tag}))
        request = fancy_urllib.FancyRequest(url)
        request.set_ssl_info(ca_certs=self._ca_certs_file)
        try:
            response = self.opener.open(request)
        except urllib2.HTTPError, e:
            raise RequestError('Failed to get status. %s' % str(e))
Ejemplo n.º 8
0
  def VerifyEscrow(self, volume_uuid):
    """Verifies if a Volume UUID has a passphrase escrowed or not.

    Args:
      volume_uuid: str, Volume UUID to verify escrow for.
    Returns:
      Boolean. True if a passphrase is escrowed, False otherwise.
    Raises:
      RequestError: there was an error querying the server.
    """
    request = fancy_urllib.FancyRequest(
        util.JoinURL(self.escrow_url, volume_uuid, '?only_verify_escrow=1'))
    request.set_ssl_info(ca_certs=self._ca_certs_file)
    try:
      self._RetryRequest(request, 'Verifying escrow')
    except urllib2.HTTPError, e:
      if e.code == 404:
        return False
      else:
        raise RequestError('Failed to verify escrow. HTTP %s' % e.code)
Ejemplo n.º 9
0
 def _FetchXsrfToken(self, action):
     request = fancy_urllib.FancyRequest(self.xsrf_url % action)
     request.set_ssl_info(ca_certs=self._ca_certs_file)
     response = self._RetryRequest(request, 'Fetching XSRF token')
     return response.read()
Ejemplo n.º 10
0
    else:
      raise AuthenticationError('Authentication: Could not get service token.')

  try:
    response_body = response.read()
    response_dict = dict(x.split('=') for x in response_body.splitlines() if x)
    assert 'Auth' in response_dict
  except AssertionError:
    raise AuthenticationError('Authentication: Service token missing.')

  # Step 2: We pass that token to App Engine, which responds with a cookie.
  params = {
      'auth': response_dict['Auth'],
      'continue': '',
      }
  req = fancy_urllib.FancyRequest(
      'https://%s/_ah/login?%s' % (hostname, urllib.urlencode(params)))
  try:
    response = opener.open(req)
  except urllib2.HTTPError:
    logging.exception('HTTPError while obtaining cookie from ClientLogin.')
    raise AuthenticationError('Authentication: Could not get cookie.')

  return opener




class CauliflowerVestClient(object):
  """Client to interact with the CauliflowerVest service."""

  ESCROW_PATH = None  # String path to escrow to, set by subclasses.