icinga2/test/remote-certificate-fixture.cpp

147 lines
5.4 KiB
C++
Raw Permalink Normal View History

Replace all existing copyright headers with `SPDX` headers I've used the following command to replace the original copyright header lines in a C-style comment block: ``` $ find . \( -type d \( -name '\..*' -o -name third-party -o -name scripts -o -name prefix -o -name malloc -o -name server -o -name docker -o -name build -o -name doc \) -prune \) -o -type f -exec perl -pi -e 's{/\*[^*]*\(\s*c\s*\)\s*(\d{4})\s*Icinga\s+GmbH[^*]*\*/}{// SPDX-FileCopyrightText: \1 Icinga GmbH <https://icinga.com>\n// SPDX-License-Identifier: GPL-2.0-or-later}gi' {} + ``` For files that use shell-style comments (#) like CMakeLists.txt, I've used this command: ``` $ find . \( -type d \( -name '\..*' -o -name third-party -o -name scripts -o -name prefix -o -name malloc -o -name server -o -name docker -o -name build -o -name doc \) -prune \) -o -type f -exec perl -pi -e 's{#.*\(\s*c\s*\)\s(\d{4})\sIcinga\s+GmbH.*}{# SPDX-FileCopyrightText: \1 Icinga GmbH <https://icinga.com>\n# SPDX-License-Identifier: GPL-2.0-or-later}gi' {} + ``` And for SQL files: ``` $ find . \( -type d \( -name '\..*' -o -name third-party -o -name scripts -o -name prefix -o -name malloc -o -name server -o -name docker -o -name build -o -name doc \) -prune \) -o -type f \( -name '*.sql' \) -exec perl -pi -e 's{--.*\(c\)\s(\d{4})\sIcinga\sGmbH.*}{-- SPDX-FileCopyrightText: \1 Icinga GmbH <https://icinga.com>\n-- SPDX-License-Identifier: GPL-2.0-or-later}gi' {} + $ find . \( -type d \( -name '\..*' -o -name third-party -o -name scripts -o -name prefix -o -name malloc -o -name server -o -name docker -o -name build -o -name doc \) -prune \) -o -type f \( -name '*.sql' \) -exec perl -pi -e 's{-- Copyright \(c\)\s(\d{4})\sIcinga\s+Development\sTeam.*}{-- SPDX-FileCopyrightText: \1 Icinga GmbH <https://icinga.com>\n-- SPDX-License-Identifier: GPL-2.0-or-later}gi' {} + ```
2026-01-27 09:06:40 -05:00
// SPDX-FileCopyrightText: 2025 Icinga GmbH <https://icinga.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "remote-certificate-fixture.hpp"
#include "remote/pkiutility.hpp"
#include <boost/algorithm/string/join.hpp>
#include <boost/range/algorithm/find.hpp>
#include <boost/range/algorithm/replace.hpp>
using namespace icinga;
RequiresCertificate::RequiresCertificate(const std::vector<String>& certs, const String& prefix)
{
auto caFixtureName = prefix + "_ca";
/* Add a fixture for setup and cleanup of the CA, if it doesn't exist yet.
*/
if (boost::range::find(m_CaFixtures, caFixtureName) == m_CaFixtures.end()) {
AddCaFixture(caFixtureName);
}
/* In case the test doesn't specify any certificates it needs to depend on the CA fixture
* directly.
*/
if (certs.empty()) {
m_RequiredFixtures.emplace_back(caFixtureName);
}
for (const auto& cert : certs) {
auto fixtureName = prefix + "_cert_" + cert;
boost::range::replace(fixtureName, '.', '_');
m_RequiredFixtures.emplace_back(fixtureName);
/* Add a fixture for the generation and cleanup of the certificate if it doesn't exist yet.
*/
if (boost::range::find(m_CertFixtures, fixtureName) == m_CertFixtures.end()) {
AddCertFixture(cert, caFixtureName, fixtureName);
}
}
}
void RequiresCertificate::AddCaFixture(const String& caFixtureName)
{
boost::unit_test::decorator::base_ptr certLabel{new boost::unit_test::label{"cert"}};
auto& mts = boost::unit_test::framework::master_test_suite();
auto* setup = boost::unit_test::make_test_case(
[]() {
CertificateFixture certFixture;
PkiUtility::NewCa();
auto persistentCaPath = CertificateFixture::m_PersistentCertsDir / "ca";
auto persistentCertsPath = CertificateFixture::m_PersistentCertsDir / "certs";
Utility::CopyFile((certFixture.m_CaDir / "ca.crt").string(), (persistentCaPath / "ca.crt").string());
Utility::CopyFile((certFixture.m_CaDir / "ca.crt").string(), (persistentCertsPath / "ca.crt").string());
Utility::CopyFile((certFixture.m_CaDir / "ca.key").string(), (persistentCaPath / "ca.key").string());
BOOST_REQUIRE(Utility::PathExists((persistentCaPath / "ca.crt").string()));
BOOST_REQUIRE(Utility::PathExists((persistentCertsPath / "ca.crt").string()));
BOOST_REQUIRE(Utility::PathExists((persistentCaPath / "ca.key").string()));
},
caFixtureName.GetData() + "_setup",
__FILE__,
__LINE__
);
setup->p_decorators.value.emplace_back(new CTestProperties{"FIXTURES_SETUP " + caFixtureName});
setup->p_decorators.value.emplace_back(certLabel);
mts.add(setup);
/* This ensures that tests operating under a different prefix will wait for the
* cleanup of another prefix to complete. For example if a group of tests operate
* destructively on certs or the CA, they would request their own prefix and
* this would ensure that the tests using that prefix run either before or after
* other tests.
*/
if (!m_CaFixtures.empty()) {
setup->p_decorators.value.emplace_back(new CTestProperties{"DEPENDS " + m_CaFixtures.back() + "_cleanup"});
}
auto* cleanup = boost::unit_test::make_test_case(
[]() {
BOOST_REQUIRE(Utility::PathExists(CertificateFixture::m_PersistentCertsDir.string()));
Utility::RemoveDirRecursive(CertificateFixture::m_PersistentCertsDir.string());
},
caFixtureName.GetData() + "_cleanup",
__FILE__,
__LINE__
);
cleanup->p_decorators.value.emplace_back(new CTestProperties{"FIXTURES_CLEANUP " + caFixtureName});
cleanup->p_decorators.value.emplace_back(certLabel);
mts.add(cleanup);
m_CaFixtures.emplace_back(caFixtureName);
}
void RequiresCertificate::AddCertFixture(const String& cn, const String& caFixture, const String& certFixture)
{
auto& mts = boost::unit_test::framework::master_test_suite();
boost::unit_test::decorator::base_ptr certLabel{new boost::unit_test::label{"cert"}};
auto* setup = boost::unit_test::make_test_case(
[cn]() {
CertificateFixture certFixture;
auto persistentCertsPath = CertificateFixture::m_PersistentCertsDir / "certs";
auto keyFile = persistentCertsPath / (cn.GetData() + ".key");
auto csrFile = persistentCertsPath / (cn.GetData() + ".csr");
auto crtFile = persistentCertsPath / (cn.GetData() + ".crt");
PkiUtility::NewCert(cn, keyFile.string(), csrFile.string(), "");
PkiUtility::SignCsr(csrFile.string(), crtFile.string());
},
certFixture.GetData() + "_setup",
__FILE__,
__LINE__
);
/* Declare this unit as the setup routine of the ctest fixture.
*/
setup->p_decorators.value.emplace_back(new CTestProperties{"FIXTURES_SETUP " + certFixture});
setup->p_decorators.value.emplace_back(certLabel);
mts.add(setup);
/* This "cleanup" fixture doesn't do anything on its own, but it is needed to enforce
* the ordering of all tests that require the certificate before the cleanup of the
* CA (defined above).
*/
auto* cleanup = boost::unit_test::make_test_case([]() {}, certFixture.GetData() + "_cleanup", __FILE__, __LINE__);
cleanup->p_decorators.value.emplace_back(new CTestProperties{"FIXTURES_CLEANUP " + certFixture});
cleanup->p_decorators.value.emplace_back(certLabel);
mts.add(cleanup);
for (auto* unit : {setup, cleanup}) {
unit->p_decorators.value.emplace_back(new CTestProperties{"FIXTURES_REQUIRED " + caFixture});
}
m_CertFixtures.push_back(certFixture);
}
std::string RequiresCertificate::Get()
{
std::string props = "FIXTURES_REQUIRED \"";
props.append(boost::algorithm::join(m_RequiredFixtures, ";"));
props.append("\"");
return props;
}