}
return transform_old_authinfo(info, std::move(account), std::move(policies), driver);
}
-
} /* namespace auth */
} /* namespace rgw */
return result_t::grant(std::move(apl));
}
}
+
+namespace rgw::auth {
+ACLOwner
+PrincipalIdentity::get_aclowner() const
+{
+ ceph_abort();
+ return {};
+}
+
+uint32_t
+PrincipalIdentity::get_perms_from_aclspec(
+ const DoutPrefixProvider* dpp,
+ const aclspec_t& aclspec) const
+{
+ ceph_abort();
+ return 0;
+}
+
+bool
+PrincipalIdentity::is_admin() const
+{
+ ceph_abort();
+ return false;
+}
+
+bool
+PrincipalIdentity::is_owner_of(const rgw_owner& owner) const
+{
+ ceph_abort();
+ return false;
+}
+
+bool
+PrincipalIdentity::is_root() const
+{
+ ceph_abort();
+ return false;
+}
+
+uint32_t
+PrincipalIdentity::get_perm_mask() const
+{
+ ceph_abort();
+ return 0;
+}
+
+std::string
+PrincipalIdentity::get_acct_name() const
+{
+ ceph_abort();
+ return {};
+}
+
+std::string
+PrincipalIdentity::get_subuser() const
+{
+ ceph_abort();
+ return {};
+}
+
+const std::string&
+PrincipalIdentity::get_tenant() const
+{
+ ceph_abort();
+ static std::string empty;
+ return empty;
+}
+
+const std::optional<RGWAccountInfo>&
+PrincipalIdentity::get_account() const
+{
+ ceph_abort();
+ static std::optional<RGWAccountInfo> empty;
+ return empty;
+}
+
+void
+PrincipalIdentity::to_str(std::ostream& out) const
+{
+ out << id;
+}
+
+bool
+PrincipalIdentity::is_identity(const Principal& p) const
+{
+ // Wildcard on either side always matches.
+ if (p.is_wildcard() || id.is_wildcard()) {
+ return true;
+ } else if (p.is_account()) {
+ // Compare account to account, since we're matching principal to principal
+ return (id.get_account() == p.get_account());
+ } else if (p.is_user() || p.is_role()) {
+ // Parse out id/path/subuser to pass to match_principal
+ std::string_view name;
+ std::string path; // We need actual storage to prepend a `/`.
+ std::string_view subuser;
+ std::string_view res{id.get_id()};
+ if (id.is_user() || id.is_role()) {
+ auto pos = res.rfind('/');
+ if (pos != res.npos) {
+ path.push_back('/');
+ path.append(res, 0, pos + 1);
+ res = res.substr(pos + 1);
+ }
+ }
+ if (p.is_user()) {
+ if (!id.is_user()) {
+ return false;
+ }
+ auto pos = res.find(':');
+ if (pos != res.npos) {
+ subuser = res.substr(pos + 1, res.npos);
+ res = res.substr(0, pos);
+ }
+ name = res;
+ } else if (p.is_role()) {
+ if (!(id.is_role() || id.is_assumed_role())) {
+ return false;
+ }
+ if (id.is_assumed_role()) {
+ auto pos = res.rfind('/');
+ name = res.substr(0, pos);
+ } else {
+ name = res;
+ }
+ }
+ return ((id.get_account() == p.get_account()) &&
+ match_principal(path, name, subuser, p.get_id()));
+ } else if (p.is_assumed_role()) {
+ // Match role/session to role/session
+ auto role_session = id.get_role_session();
+ if (auto pos = role_session.rfind('/');
+ (pos != role_session.npos) && (pos != 0)) {
+ if (pos = role_session.rfind('/', pos - 1); pos != role_session.npos) {
+ role_session = role_session.substr(pos + 1);
+ }
+ }
+ return (id.is_assumed_role() && (id.get_account() == p.get_account()) &&
+ (role_session == p.get_role_session()));
+ } else if (p.is_oidc_provider()) {
+ return id.is_oidc_provider() && id.get_idp_url() == p.get_idp_url();
+ } else if (p.is_service()) {
+ return id.is_service() && id.get_service() == p.get_service();
+ }
+ return false;
+}
+
+uint32_t
+PrincipalIdentity::get_identity_type() const
+{
+ if (id.is_role() || id.is_assumed_role()) {
+ return TYPE_ROLE;
+ } else if (id.is_oidc_provider()) {
+ return TYPE_WEB;
+ } else {
+ return TYPE_RGW;
+ }
+}
+
+std::optional<rgw::ARN>
+PrincipalIdentity::get_caller_identity() const
+{
+ return std::nullopt;
+}
+} // namespace rgw::auth
}
};
+// A Principal-only identity disconnected from any backends for use in
+// testing and utilities.
+class PrincipalIdentity : public Identity {
+ const Principal id;
+public:
+
+ explicit PrincipalIdentity(Principal&& id) : id(std::move(id)) {}
+
+ // These exist to meet the interface requirement but are
+ // unimplemented and will `abort()`.
+ ACLOwner get_aclowner() const override;
+ uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override;
+ bool is_admin() const override;
+ bool is_owner_of(const rgw_owner& owner) const override;
+ bool is_root() const override;
+ uint32_t get_perm_mask() const override;
+ std::string get_acct_name() const override;
+ std::string get_subuser() const override;
+ const std::string& get_tenant() const override;
+ const std::optional<RGWAccountInfo>& get_account() const override;
+ void to_str(std::ostream& out) const override;
+
+ // Predict whether the server would consider this identity to match a
+ // policy principal `p`, mirroring the structural matching in
+ // rgw::auth::LocalApplier::is_identity (users) and
+ // RoleApplier::is_identity (roles and assumed-role sessions) as far as
+ // the tool's Principal-only identity model allows.
+ bool is_identity(const Principal& p) const override;
+
+ // A role or an assumed-role session evaluates trust policies
+ // through the TYPE_ROLE branch of Statement::eval_principal;
+ // reflect that so rather than always reporting TYPE_RGW.
+ uint32_t get_identity_type() const override;
+ std::optional<rgw::ARN> get_caller_identity() const override;
+};
+
+
} /* namespace auth */
} /* namespace rgw */
return t == Service;
}
- const std::string& get_account() const {
+ std::string_view get_account() const {
return u.tenant;
}
- const std::string& get_id() const {
+ std::string_view get_id() const {
return u.id;
}
- const std::string& get_idp_url() const {
+ std::string_view get_idp_url() const {
return idp_url;
}
- const std::string& get_role_session() const {
+ std::string_view get_role_session() const {
return u.id;
}
- const std::string& get_role() const {
+ std::string_view get_role() const {
return u.id;
}
- const std::string& get_service() const {
+ std::string_view get_service() const {
return service_id;
}
using rgw::auth::Identity;
using rgw::auth::Principal;
+using rgw::auth::PrincipalIdentity;
using rgw::ARN;
using rgw::IAM::Effect;
using rgw::IAM::get_managed_policy;
-class FakeIdentity : public Identity {
- const Principal id;
-public:
-
- explicit FakeIdentity(Principal&& id) : id(std::move(id)) {}
-
- ACLOwner get_aclowner() const override {
- ceph_abort();
- return {};
- }
-
- uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override {
- ceph_abort();
- return 0;
- };
-
- bool is_admin() const override {
- ceph_abort();
- return false;
- }
-
- bool is_owner_of(const rgw_owner& owner) const override {
- ceph_abort();
- return false;
- }
-
- bool is_root() const override {
- ceph_abort();
- return false;
- }
-
- virtual uint32_t get_perm_mask() const override {
- ceph_abort();
- return 0;
- }
-
- string get_acct_name() const override {
- abort();
- return string{};
- }
-
- string get_subuser() const override {
- abort();
- return string{};
- }
-
- const std::string& get_tenant() const override {
- ceph_abort();
- static std::string empty;
- return empty;
- }
-
- const std::optional<RGWAccountInfo>& get_account() const override {
- ceph_abort();
- static std::optional<RGWAccountInfo> empty;
- return empty;
- }
-
- void to_str(std::ostream& out) const override {
- out << id;
- }
-
- bool is_identity(const Principal& p) const override {
- return id.is_wildcard() || p.is_wildcard() || p == id;
- }
-
- uint32_t get_identity_type() const override {
- return TYPE_RGW;
- }
-
- std::optional<rgw::ARN> get_caller_identity() const override {
- return std::nullopt;
- }
-};
-
class PolicyTest : public ::testing::Test {
protected:
intrusive_ptr<CephContext> cct;
auto p = Policy(cct.get(), &arbitrary_tenant, example2, true);
Environment e;
- auto trueacct = FakeIdentity(
+ auto trueacct = PrincipalIdentity(
Principal::account("ACCOUNT-ID-WITHOUT-HYPHENS"));
- auto notacct = FakeIdentity(
+ auto notacct = PrincipalIdentity(
Principal::account("some-other-account"));
for (auto i = 0ULL; i < s3All; ++i) {
ARN arn1(Partition::aws, Service::s3,
auto p = Policy(cct.get(), &arbitrary_tenant, example7, true);
Environment e;
- auto subacct = FakeIdentity(
+ auto subacct = PrincipalIdentity(
Principal::user(std::move(""), "A:subA"));
- auto parentacct = FakeIdentity(
+ auto parentacct = PrincipalIdentity(
Principal::user(std::move(""), "A"));
- auto sub2acct = FakeIdentity(
+ auto sub2acct = PrincipalIdentity(
Principal::user(std::move(""), "A:sub2A"));
ARN arn1(Partition::aws, Service::s3,
blocklistedIP.emplace("aws:SourceIp", "192.168.1.1");
blocklistedIPv6.emplace("aws:SourceIp", "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
- auto trueacct = FakeIdentity(
+ auto trueacct = PrincipalIdentity(
Principal::account("ACCOUNT-ID-WITHOUT-HYPHENS"));
// Without an IP address in the environment then evaluation will always pass
ARN arn1(Partition::aws, Service::s3,