示例#1
0
  def __init__(self):
    """Initializes this class.

    """
    username = utils.GenerateSecret()
    password = utils.GenerateSecret()

    # pylint: disable=W0232
    class SimpleAuthenticator():
      # pylint: disable=R0201
      def ValidateRequest(self, req, _handler_access, _realm):
        """Called to verify user credentials given in HTTP request.

        """
        wanted, _ = http.auth.HttpServerRequestAuthentication \
                      .ExtractUserPassword(req)
        assert username == wanted
        return users_file.PasswordFileUser(username, password,
                                           [rapi.RAPI_ACCESS_WRITE]).name

    self._lcr = _LuxiCallRecorder()

    # Create a mock RAPI server
    handler = _RapiMock(SimpleAuthenticator(), self._lcr)

    self._client = \
      rapi.client.GanetiRapiClient("master.example.com",
                                   username=username, password=password,
                                   curl_factory=lambda: FakeCurl(handler))
示例#2
0
文件: qa_rapi.py 项目: vali-um/ganeti
def _CreateRapiUser(rapi_user):
    """RAPI credentials creation, with the secret auto-generated.

  """
    rapi_secret = utils.GenerateSecret()

    master = qa_config.GetMasterNode()

    rapi_users_path = qa_utils.MakeNodePath(master, pathutils.RAPI_USERS_FILE)
    rapi_dir = os.path.dirname(rapi_users_path)

    fh = tempfile.NamedTemporaryFile(mode="w")
    try:
        fh.write("%s %s write\n" % (rapi_user, rapi_secret))
        fh.flush()

        tmpru = qa_utils.UploadFile(master.primary, fh.name)
        try:
            AssertCommand(["mkdir", "-p", rapi_dir])
            AssertCommand(["mv", tmpru, rapi_users_path])
        finally:
            AssertCommand(["rm", "-f", tmpru])
    finally:
        fh.close()

    # The certificates have to be reloaded now
    AssertCommand(["service", "ganeti", "restart"])

    return rapi_secret
示例#3
0
    def Exec(self, feedback_fn):
        """Prepares an instance for an export.

    """
        if self.op.mode == constants.EXPORT_MODE_REMOTE:
            salt = utils.GenerateSecret(8)

            feedback_fn("Generating X509 certificate on %s" %
                        self.cfg.GetNodeName(self.instance.primary_node))
            result = self.rpc.call_x509_cert_create(
                self.instance.primary_node, constants.RIE_CERT_VALIDITY)
            result.Raise("Can't create X509 key and certificate on %s" %
                         self.cfg.GetNodeName(result.node))

            (name, cert_pem) = result.payload

            cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                                   cert_pem)

            return {
                "handshake":
                masterd.instance.ComputeRemoteExportHandshake(self._cds),
                "x509_key_name":
                (name, utils.Sha1Hmac(self._cds, name, salt=salt), salt),
                "x509_ca":
                utils.SignX509Certificate(cert, self._cds, salt),
            }

        return None
示例#4
0
  def __init__(self, feedback_fn, cds, x509_cert_pem, disk_count,
               external_address):
    """Initializes this class.

    @type cds: string
    @param cds: Cluster domain secret
    @type x509_cert_pem: string
    @param x509_cert_pem: CA used for signing import key
    @type disk_count: number
    @param disk_count: Number of disks
    @type external_address: string
    @param external_address: External address of destination node

    """
    ImportExportCbBase.__init__(self)
    self._feedback_fn = feedback_fn
    self._cds = cds
    self._x509_cert_pem = x509_cert_pem
    self._disk_count = disk_count
    self._external_address = external_address

    self._dresults = [None] * disk_count
    self._daemon_port = [None] * disk_count

    self._salt = utils.GenerateSecret(8)
示例#5
0
def GenerateHmacKey(file_name):
  """Writes a new HMAC key.

  @type file_name: str
  @param file_name: Path to output file

  """
  utils.WriteFile(file_name, data="%s\n" % utils.GenerateSecret(), mode=0400,
                  backup=True)
示例#6
0
    def test(self):
        # Generate certificate valid for 5 minutes
        (_, cert_pem) = utils.GenerateSelfSignedX509Cert(None, 300, 1)

        cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                               cert_pem)

        # No signature at all
        self.assertRaises(errors.GenericError, utils.LoadSignedX509Certificate,
                          cert_pem, self.KEY)

        # Invalid input
        self.assertRaises(errors.GenericError, utils.LoadSignedX509Certificate,
                          "", self.KEY)
        self.assertRaises(errors.GenericError, utils.LoadSignedX509Certificate,
                          "X-Ganeti-Signature: \n", self.KEY)
        self.assertRaises(errors.GenericError, utils.LoadSignedX509Certificate,
                          "X-Ganeti-Sign: $1234$abcdef\n", self.KEY)
        self.assertRaises(errors.GenericError, utils.LoadSignedX509Certificate,
                          "X-Ganeti-Signature: $1234567890$abcdef\n", self.KEY)
        self.assertRaises(errors.GenericError, utils.LoadSignedX509Certificate,
                          b"X-Ganeti-Signature: $1234$abc\n\n" + cert_pem,
                          self.KEY)

        # Invalid salt
        for salt in list("-_@$,:;/\\ \t\n"):
            self.assertRaises(errors.GenericError, utils.SignX509Certificate,
                              cert_pem, self.KEY, "foo%sbar" % salt)

        for salt in [
                "HelloWorld", "salt", string.ascii_letters, string.digits,
                utils.GenerateSecret(numbytes=4),
                utils.GenerateSecret(numbytes=16),
                "{123:456}".encode("ascii").hex()
        ]:
            signed_pem = utils.SignX509Certificate(cert, self.KEY, salt)

            self._Check(cert, salt, signed_pem)

            self._Check(cert, salt,
                        "X-Another-Header: with a value\n" + signed_pem)
            self._Check(cert, salt, (10 * "Hello World!\n") + signed_pem)
            self._Check(cert, salt, (signed_pem + "\n\na few more\n"
                                     "lines----\n------ at\nthe end!"))
示例#7
0
def ComputeRemoteExportHandshake(cds):
  """Computes the remote import/export handshake.

  @type cds: string
  @param cds: Cluster domain secret

  """
  salt = utils.GenerateSecret(8)
  msg = _GetImportExportHandshakeMessage(constants.RIE_VERSION)
  return (constants.RIE_VERSION, utils.Sha1Hmac(cds, msg, salt=salt), salt)
示例#8
0
    def __init__(self):
        """Initializes this class.

    """
        username = utils.GenerateSecret()
        password = utils.GenerateSecret()

        def user_fn(wanted):
            """Called to verify user credentials given in HTTP request.

      """
            assert username == wanted
            return http.auth.PasswordFileUser(username, password,
                                              [rapi.RAPI_ACCESS_WRITE])

        self._lcr = _LuxiCallRecorder()

        # Create a mock RAPI server
        handler = _RapiMock(user_fn, self._lcr)

        self._client = \
          rapi.client.GanetiRapiClient("master.example.com",
                                       username=username, password=password,
                                       curl_factory=lambda: FakeCurl(handler))
示例#9
0
def SetupCluster(rapi_user):
    """Initializes the cluster.

  @param rapi_user: Login user for RAPI
  @return: Login secret for RAPI

  """
    rapi_secret = utils.GenerateSecret()
    RunTestIf("create-cluster", qa_cluster.TestClusterInit, rapi_user,
              rapi_secret)
    if not qa_config.TestEnabled("create-cluster"):
        # If the cluster is already in place, we assume that exclusive-storage is
        # already set according to the configuration
        qa_config.SetExclusiveStorage(qa_config.get("exclusive-storage",
                                                    False))
        if qa_rapi.Enabled():
            # To support RAPI on an existing cluster we have to find out the secret
            rapi_secret = qa_rapi.LookupRapiSecret(rapi_user)

    qa_group.ConfigureGroups()

    # Test on empty cluster
    RunTestIf("node-list", qa_node.TestNodeList)
    RunTestIf("instance-list", qa_instance.TestInstanceList)
    RunTestIf("job-list", qa_job.TestJobList)

    RunTestIf("create-cluster", qa_node.TestNodeAddAll)
    if not qa_config.TestEnabled("create-cluster"):
        # consider the nodes are already there
        qa_node.MarkNodeAddedAll()

    RunTestIf("test-jobqueue", qa_cluster.TestJobqueue)
    RunTestIf("test-jobqueue", qa_job.TestJobCancellation)

    # enable the watcher (unconditionally)
    RunTest(qa_daemon.TestResumeWatcher)

    RunTestIf("node-list", qa_node.TestNodeList)

    # Test listing fields
    RunTestIf("node-list", qa_node.TestNodeListFields)
    RunTestIf("instance-list", qa_instance.TestInstanceListFields)
    RunTestIf("job-list", qa_job.TestJobListFields)
    RunTestIf("instance-export", qa_instance.TestBackupListFields)

    RunTestIf("node-info", qa_node.TestNodeInfo)

    return rapi_secret
示例#10
0
def TestClusterRenewCrypto():
    """gnt-cluster renew-crypto"""
    master = qa_config.GetMasterNode()

    # Conflicting options
    cmd = [
        "gnt-cluster", "renew-crypto", "--force", "--new-cluster-certificate",
        "--new-confd-hmac-key"
    ]
    conflicting = [
        ["--new-rapi-certificate", "--rapi-certificate=/dev/null"],
        ["--new-cluster-domain-secret", "--cluster-domain-secret=/dev/null"],
    ]
    for i in conflicting:
        AssertCommand(cmd + i, fail=True)

    # Invalid RAPI certificate
    cmd = [
        "gnt-cluster", "renew-crypto", "--force",
        "--rapi-certificate=/dev/null"
    ]
    AssertCommand(cmd, fail=True)

    rapi_cert_backup = qa_utils.BackupFile(master.primary,
                                           pathutils.RAPI_CERT_FILE)
    try:
        # Custom RAPI certificate
        fh = tempfile.NamedTemporaryFile()

        # Ensure certificate doesn't cause "gnt-cluster verify" to complain
        validity = constants.SSL_CERT_EXPIRATION_WARN * 3

        utils.GenerateSelfSignedSslCert(fh.name, validity=validity)

        tmpcert = qa_utils.UploadFile(master.primary, fh.name)
        try:
            AssertCommand([
                "gnt-cluster", "renew-crypto", "--force",
                "--rapi-certificate=%s" % tmpcert
            ])
        finally:
            AssertCommand(["rm", "-f", tmpcert])

        # Custom cluster domain secret
        cds_fh = tempfile.NamedTemporaryFile()
        cds_fh.write(utils.GenerateSecret())
        cds_fh.write("\n")
        cds_fh.flush()

        tmpcds = qa_utils.UploadFile(master.primary, cds_fh.name)
        try:
            AssertCommand([
                "gnt-cluster", "renew-crypto", "--force",
                "--cluster-domain-secret=%s" % tmpcds
            ])
        finally:
            AssertCommand(["rm", "-f", tmpcds])

        # Normal case
        AssertCommand([
            "gnt-cluster", "renew-crypto", "--force",
            "--new-cluster-certificate", "--new-confd-hmac-key",
            "--new-rapi-certificate", "--new-cluster-domain-secret"
        ])

        # Restore RAPI certificate
        AssertCommand([
            "gnt-cluster", "renew-crypto", "--force",
            "--rapi-certificate=%s" % rapi_cert_backup
        ])
    finally:
        AssertCommand(["rm", "-f", rapi_cert_backup])
示例#11
0
def RemoteImport(lu, feedback_fn, instance, pnode, source_x509_ca,
                 cds, compress, timeouts):
  """Imports an instance from another cluster.

  @param lu: Logical unit instance
  @param feedback_fn: Feedback function
  @type instance: L{objects.Instance}
  @param instance: Instance object
  @type pnode: L{objects.Node}
  @param pnode: Primary node of instance as an object
  @type source_x509_ca: OpenSSL.crypto.X509
  @param source_x509_ca: Import source's X509 CA
  @type cds: string
  @param cds: Cluster domain secret
  @type compress: string
  @param compress: Compression tool to use
  @type timeouts: L{ImportExportTimeouts}
  @param timeouts: Timeouts for this import

  """
  source_ca_pem = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                                  source_x509_ca)

  magic_base = utils.GenerateSecret(6)

  # Decide whether to use IPv6
  ipv6 = netutils.IP6Address.IsValid(pnode.primary_ip)

  # Create crypto key
  result = lu.rpc.call_x509_cert_create(instance.primary_node,
                                        constants.RIE_CERT_VALIDITY)
  result.Raise("Can't create X509 key and certificate on %s" % result.node)

  (x509_key_name, x509_cert_pem) = result.payload
  try:
    # Load certificate
    x509_cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                                x509_cert_pem)

    # Sign certificate
    signed_x509_cert_pem = \
      utils.SignX509Certificate(x509_cert, cds, utils.GenerateSecret(8))

    cbs = _RemoteImportCb(feedback_fn, cds, signed_x509_cert_pem,
                          len(instance.disks), pnode.primary_ip)

    ieloop = ImportExportLoop(lu)
    inst_disks = lu.cfg.GetInstanceDisks(instance.uuid)
    try:
      for idx, dev in enumerate(inst_disks):
        magic = _GetInstDiskMagic(magic_base, instance.name, idx)

        # Import daemon options
        opts = objects.ImportExportOptions(key_name=x509_key_name,
                                           ca_pem=source_ca_pem,
                                           magic=magic,
                                           compress=compress,
                                           ipv6=ipv6)

        if instance.os:
          src_io = constants.IEIO_SCRIPT
          src_ioargs = ((dev, instance), idx)
        else:
          src_io = constants.IEIO_RAW_DISK
          src_ioargs = (dev, instance)

        ieloop.Add(DiskImport(lu, instance.primary_node, opts, instance,
                              "disk%d" % idx,
                              src_io, src_ioargs,
                              timeouts, cbs, private=(idx, )))

      ieloop.Run()
    finally:
      ieloop.FinalizeAll()
  finally:
    # Remove crypto key and certificate
    result = lu.rpc.call_x509_cert_remove(instance.primary_node, x509_key_name)
    result.Raise("Can't remove X509 key and certificate on %s" % result.node)

  return cbs.disk_results
示例#12
0
def TransferInstanceData(lu, feedback_fn, src_node_uuid, dest_node_uuid,
                         dest_ip, compress, instance, all_transfers):
  """Transfers an instance's data from one node to another.

  @param lu: Logical unit instance
  @param feedback_fn: Feedback function
  @type src_node_uuid: string
  @param src_node_uuid: Source node UUID
  @type dest_node_uuid: string
  @param dest_node_uuid: Destination node UUID
  @type dest_ip: string
  @param dest_ip: IP address of destination node
  @type compress: string
  @param compress: Compression tool to use
  @type instance: L{objects.Instance}
  @param instance: Instance object
  @type all_transfers: list of L{DiskTransfer} instances
  @param all_transfers: List of all disk transfers to be made
  @rtype: list
  @return: List with a boolean (True=successful, False=failed) for success for
           each transfer

  """
  src_node_name = lu.cfg.GetNodeName(src_node_uuid)
  dest_node_name = lu.cfg.GetNodeName(dest_node_uuid)

  logging.debug("Source node %s, destination node %s, compression '%s'",
                src_node_name, dest_node_name, compress)

  timeouts = ImportExportTimeouts(constants.DISK_TRANSFER_CONNECT_TIMEOUT)
  src_cbs = _TransferInstSourceCb(lu, feedback_fn, instance, timeouts,
                                  src_node_uuid, None, dest_node_uuid, dest_ip)
  dest_cbs = _TransferInstDestCb(lu, feedback_fn, instance, timeouts,
                                 src_node_uuid, src_cbs, dest_node_uuid,
                                 dest_ip)

  all_dtp = []

  base_magic = utils.GenerateSecret(6)

  ieloop = ImportExportLoop(lu)
  try:
    for idx, transfer in enumerate(all_transfers):
      if transfer:
        feedback_fn("Exporting %s from %s to %s" %
                    (transfer.name, src_node_name, dest_node_name))

        magic = _GetInstDiskMagic(base_magic, instance.name, idx)
        opts = objects.ImportExportOptions(key_name=None, ca_pem=None,
                                           compress=compress, magic=magic)

        dtp = _DiskTransferPrivate(transfer, True, opts)

        di = DiskImport(lu, dest_node_uuid, opts, instance, "disk%d" % idx,
                        transfer.dest_io, transfer.dest_ioargs,
                        timeouts, dest_cbs, private=dtp)
        ieloop.Add(di)

        dtp.dest_import = di
      else:
        dtp = _DiskTransferPrivate(None, False, None)

      all_dtp.append(dtp)

    ieloop.Run()
  finally:
    ieloop.FinalizeAll()

  assert len(all_dtp) == len(all_transfers)
  assert compat.all((dtp.src_export is None or
                      dtp.src_export.success is not None) and
                     (dtp.dest_import is None or
                      dtp.dest_import.success is not None)
                     for dtp in all_dtp), \
         "Not all imports/exports are finalized"

  return [bool(dtp.success) for dtp in all_dtp]