int fizzGenerateDelegatedCredentialCommand()

in fizz/tool/FizzGenerateDelegatedCredentialCommand.cpp [40:180]


int fizzGenerateDelegatedCredentialCommand(
    const std::vector<std::string>& args) {
  // clang-format off
  std::string certPath;
  std::string certKeyPath;
  std::string credKeyPath;
  std::string certKeyPass;
  std::string credKeyPass;
  Optional<SignatureScheme> credSignScheme;
  Optional<SignatureScheme> credVerifScheme;
  std::chrono::seconds validSec{86400}; // 1 day
  std::string outPath;

  FizzArgHandlerMap handlers = {
    {"-cert", {true, [&certPath](const std::string& arg) { certPath = arg; }}},
    {"-key", {true, [&certKeyPath](const std::string& arg) { certKeyPath = arg; }}},
    {"-pass", {true, [&certKeyPass](const std::string& arg) { certKeyPass = arg; }}},
    {"-credkey", {true, [&credKeyPath](const std::string& arg) { credKeyPath = arg; }}},
    {"-credpass", {true, [&credKeyPass](const std::string& arg) { credKeyPass = arg; }}},
    {"-signscheme", {true, [&credSignScheme](const std::string& arg) {
        credSignScheme = parse<SignatureScheme>(arg);
    }}},
    {"-verifscheme", {true, [&credVerifScheme](const std::string& arg) {
        credVerifScheme = parse<SignatureScheme>(arg);
    }}},
    {"-validsec", {true, [&validSec](const std::string& arg) {
        validSec = std::chrono::seconds(std::stoul(arg));
    }}},
    {"-out", {true, [&outPath](const std::string& arg) {
        outPath = arg;
    }}}
  };
  // clang-format on

  try {
    if (parseArguments(args, handlers, printUsage)) {
      // Parsing failed, return
      return 1;
    }
  } catch (const std::exception& e) {
    LOG(ERROR) << "Error: " << e.what();
    return 1;
  }

  if (certPath.empty()) {
    LOG(ERROR) << "-cert is a required argument for gendc";
    printUsage();
    return 1;
  }

  if (certKeyPath.empty()) {
    LOG(ERROR) << "-key is a required argument for gendc";
    printUsage();
    return 1;
  }

  if (credKeyPath.empty()) {
    LOG(ERROR) << "-credkey is a required argument for gendc";
    printUsage();
    return 1;
  }

  std::string certData;
  std::string certKeyData;
  std::string credKeyData;
  if (!readFile(certPath.c_str(), certData)) {
    LOG(ERROR) << "Failed to read certificate";
    return 1;
  } else if (!readFile(certKeyPath.c_str(), certKeyData)) {
    LOG(ERROR) << "Failed to read cert private key";
    return 1;
  } else if (!readFile(credKeyPath.c_str(), credKeyData)) {
    LOG(ERROR) << "Failed to read credential private key";
    return 1;
  }

  try {
    std::shared_ptr<SelfCert> cert;
    if (!certKeyPass.empty()) {
      cert = CertUtils::makeSelfCert(certData, certKeyData, certKeyPass);
    } else {
      cert = CertUtils::makeSelfCert(certData, certKeyData);
    }

    folly::ssl::EvpPkeyUniquePtr certPrivKey =
        CertUtils::readPrivateKeyFromBuffer(
            certKeyData, certKeyPass.empty() ? nullptr : &certKeyPass[0]);

    folly::ssl::EvpPkeyUniquePtr credPrivKey =
        CertUtils::readPrivateKeyFromBuffer(
            credKeyData, credKeyPass.empty() ? nullptr : &credKeyPass[0]);

    if (!credSignScheme) {
      credSignScheme = cert->getSigSchemes().front();
    }

    if (!credVerifScheme) {
      switch (CertUtils::getKeyType(credPrivKey)) {
        case KeyType::RSA:
          credVerifScheme = CertUtils::getSigSchemes<KeyType::RSA>().front();
          break;
        case KeyType::P256:
          credVerifScheme = CertUtils::getSigSchemes<KeyType::P256>().front();
          break;
        case KeyType::P384:
          credVerifScheme = CertUtils::getSigSchemes<KeyType::P384>().front();
          break;
        case KeyType::P521:
          credVerifScheme = CertUtils::getSigSchemes<KeyType::P521>().front();
          break;
        case KeyType::ED25519:
          credVerifScheme =
              CertUtils::getSigSchemes<KeyType::ED25519>().front();
          break;
      }
    }

    auto credential = DelegatedCredentialUtils::generateCredential(
        std::move(cert),
        certPrivKey,
        credPrivKey,
        *credSignScheme,
        *credVerifScheme,
        validSec);
    auto encodedCred = fizz::extensions::encodeExtension(credential);
    auto credData = encodedCred.extension_data->moveToFbString().toStdString();
    if (outPath.empty()) {
      std::cout << credData;
    } else {
      if (!writeFile(credData, outPath.c_str())) {
        LOG(ERROR) << "Failed to write out credential: " << errnoStr(errno);
        return 1;
      }
    }
  } catch (const std::exception& e) {
    LOG(ERROR) << "Failed to generate credential: " << e.what();
    return 1;
  }

  return 0;
}