[cpp-sp] 03/03: Add TimeSinceAuthn tests.
Scott Cantor
cantor.2 at osu.edu
Mon Oct 27 18:41:37 UTC 2025
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository cpp-sp.
View the commit online:
https://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=ec2010410245902269ed0acafa85d1d592897bcf
commit ec2010410245902269ed0acafa85d1d592897bcf
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Oct 27 14:41:19 2025 -0400
Add TimeSinceAuthn tests.
---
tests/data/impl/acl/time/inline-timesinceauth.xml | 3 +
tests/impl/TimeAccessControlTests.cpp | 374 ++++++++++++++++++++++
2 files changed, 377 insertions(+)
diff --git a/tests/data/impl/acl/time/inline-timesinceauth.xml b/tests/data/impl/acl/time/inline-timesinceauth.xml
new file mode 100644
index 00000000..2b3c69fe
--- /dev/null
+++ b/tests/data/impl/acl/time/inline-timesinceauth.xml
@@ -0,0 +1,3 @@
+<AccessControlProvider type="Time">
+ <TimeSinceAuthn>PT1H</TimeSinceAuthn>
+</AccessControlProvider>
diff --git a/tests/impl/TimeAccessControlTests.cpp b/tests/impl/TimeAccessControlTests.cpp
new file mode 100644
index 00000000..8f1ec50f
--- /dev/null
+++ b/tests/impl/TimeAccessControlTests.cpp
@@ -0,0 +1,374 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * TimeAccessControlTests.cpp
+ *
+ * Unit tests for Time AccessControl implementation.
+ */
+
+#include "exceptions.h"
+#include "AbstractSPRequest.h"
+#include "AccessControl.h"
+#include "AgentConfig.h"
+#include "logging/Category.h"
+#include "remoting/ddf.h"
+#include "session/SessionCache.h"
+#include "util/BoostPropertySet.h"
+
+#include "DummyRequest.h"
+
+#ifdef HAVE_CXX14
+# include <shared_mutex>
+#endif
+
+#include <boost/test/unit_test.hpp>
+#include <boost/property_tree/xml_parser.hpp>
+
+using namespace shibsp;
+using namespace boost::property_tree;
+using namespace std;
+
+#define DATA_PATH "./data/impl/acl/time/"
+
+namespace {
+
+/** Open structure for testing manipulation. */
+struct DummySession : public Session, public NoOpBasicLockable {
+public:
+ DummySession() {}
+ ~DummySession() {
+ for (auto& a : m_attributes) {
+ a.second.destroy();
+ }
+ }
+
+ const char* getID() const {
+ return nullptr;
+ }
+ unsigned int getVersion() const {
+ return 1;
+ }
+ const char* getApplicationID() const {
+ return nullptr;
+ }
+ time_t getCreation() const {
+ return 0;
+ }
+ time_t getLastAccess() const {
+ return 0;
+ }
+ const map<string,DDF>& getAttributes() const {
+ return m_attributes;
+ }
+ DDF getOpaqueData() const {
+ return DDF();
+ }
+
+ map<string,DDF> m_attributes;
+};
+
+class MappableDummyRequest : public DummyRequest {
+public:
+ MappableDummyRequest() {}
+ ~MappableDummyRequest() {}
+ RequestMapper::Settings getRequestSettings() const { return make_pair(&m_map, nullptr); }
+
+ BoostPropertySet m_map;
+};
+
+class exceptionCheck {
+public:
+ exceptionCheck(const string& msg) : m_msg(msg) {}
+ bool check_message(const exception& e) {
+ if (m_msg.compare(e.what()) == 0) {
+ return true;
+ }
+ else {
+ cout << "Non-matching message: " << e.what() << endl;
+ return false;
+ }
+ }
+private:
+ string m_msg;
+};
+
+struct TimeAccessControlFixture
+{
+ TimeAccessControlFixture() : data_path(DATA_PATH) {
+ AgentConfig::getConfig().init(nullptr, (data_path + "../../console-agent.ini").c_str(), true);
+ }
+ ~TimeAccessControlFixture() {
+ AgentConfig::getConfig().term();
+ }
+
+ void parse(const string& filename) {
+ xml_parser::read_xml(data_path + filename, tree, xml_parser::no_comments|xml_parser::trim_whitespace);
+ }
+
+ ptree tree;
+ string data_path;
+};
+
+/////////////
+// File pointing to external ACL file that's invalid XML.
+/////////////
+
+BOOST_FIXTURE_TEST_CASE(TimeAccessControl_external_invalid, TimeAccessControlFixture)
+{
+ parse("external-acl-badxml.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ exceptionCheck checker("Initial AccessControl configuration was invalid.");
+ BOOST_CHECK_EXCEPTION(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true),
+ ConfigurationException, checker.check_message);
+}
+
+/////////////
+// Inline ACL content that has a bad internal element.
+/////////////
+
+BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_invalid_internal, TimeAccessControlFixture)
+{
+ parse("internal-acl-invalid2.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ exceptionCheck checker("Time-based rule requires element content of the form \"LT|LE|EQ|GE|GT value\".");
+ BOOST_CHECK_EXCEPTION(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true),
+ ConfigurationException, checker.check_message);
+}
+
+/////////////
+// Inline ACL test for user rule.
+/////////////
+
+BOOST_FIXTURE_TEST_CASE(TimeAccessControl_inline_TimeSinceAuthn, TimeAccessControlFixture)
+{
+ parse("inline-timesinceauth.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ // No attribute available.
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+
+ DDF ac("Shib-Authentication-Instant");
+ ac.list();
+ ac.add(DDF(nullptr).longinteger(time(nullptr) - 300));
+ session.m_attributes[ac.name()] = ac;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
+
+ ac.first().longinteger(time(nullptr) - 7200);
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+}
+
+/*
+
+/////////////
+// Inline ACL test for user regex rule.
+/////////////
+
+BOOST_FIXTURE_TEST_CASE(XMLAccessControl_inline_UserRegexRule, XMLAccessControlFixture)
+{
+ parse("inline-user-regex-acl.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ request.m_user = "smith";
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+
+ request.m_user = "extrajdoe";
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+
+ request.m_user = "jdoe";
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
+}
+
+/////////////
+// Inline ACL test for authnContextClassRef rule.
+/////////////
+
+BOOST_FIXTURE_TEST_CASE(XMLAccessControl_inline_ACRule, XMLAccessControlFixture)
+{
+ parse("inline-ac-acl.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ DDF ac("Shib-AuthnContext-Class");
+ ac.list();
+ ac.add(DDF(nullptr).string("Foo"));
+ session.m_attributes[ac.name()] = ac;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+
+ ac.add(DDF(nullptr).string("urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken"));
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
+}
+
+/////////////
+// Inline ACL test for attribute rule.
+/////////////
+
+BOOST_FIXTURE_TEST_CASE(XMLAccessControl_inline_AttrRule, XMLAccessControlFixture)
+{
+ parse("inline-attr-acl.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ DDF affiliation("affiliation");
+ affiliation.list();
+ session.m_attributes[affiliation.name()] = affiliation;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+
+ affiliation.add(DDF(nullptr).string("staff"));
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+
+ affiliation.add(DDF(nullptr).string("student"));
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
+}
+
+/////////////
+// External ACL test for OR operator
+/////////////
+
+BOOST_FIXTURE_TEST_CASE(XMLAccessControl_external_OR, XMLAccessControlFixture)
+{
+ parse("external-or-acl.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ request.m_user = "jdoe";
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
+
+ request.m_user = "smith";
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+
+ DDF affiliation("affiliation");
+ affiliation.list();
+ affiliation.add(DDF(nullptr).string("student"));
+ session.m_attributes[affiliation.name()] = affiliation;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
+}
+
+/////////////
+// External ACL test for AND operator
+/////////////
+
+BOOST_FIXTURE_TEST_CASE(XMLAccessControl_external_AND, XMLAccessControlFixture)
+{
+ parse("external-and-acl.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ request.m_user = "jdoe";
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+
+ DDF affiliation("affiliation");
+ affiliation.list();
+ affiliation.add(DDF(nullptr).string("student"));
+ session.m_attributes[affiliation.name()] = affiliation;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
+}
+
+/////////////
+// External ACL test for NOT operator
+/////////////
+
+BOOST_FIXTURE_TEST_CASE(XMLAccessControl_external_NOT, XMLAccessControlFixture)
+{
+ parse("external-not-acl.xml");
+ BOOST_CHECK_EQUAL(tree.size(), 1);
+
+ unique_ptr<AccessControl> acl(AgentConfig::getConfig().AccessControlManager.newPlugin(
+ tree.front().second.get<string>("<xmlattr>.type").c_str(), tree.front().second, true));
+
+#ifdef HAVE_CXX14
+ shared_lock locker(*acl);
+#endif
+
+ MappableDummyRequest request;
+ DummySession session;
+
+ DDF affiliation("affiliation");
+ affiliation.list();
+ session.m_attributes[affiliation.name()] = affiliation;
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_true);
+
+ affiliation.add(DDF(nullptr).string("student"));
+
+ BOOST_CHECK_EQUAL(acl->authorized(request, &session), AccessControl::shib_acl_false);
+}
+*/
+
+};
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list