blob: 6601d1cc855646d2effc855c28428ab58e10bc3b [file] [log] [blame] [edit]
#include "subscription_tracker.h"
#include <optional>
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/substitute.h"
#include "absl/synchronization/mutex.h"
#include "config_parser.h"
namespace milotic::authz {
namespace {
constexpr int kDefaultSubscriptionLimit = 1;
} // namespace
SubscriptionTracker::SubscriptionTracker()
: SubscriptionTracker(kDefaultSubscriptionLimit) {}
absl::Status SubscriptionTracker::RecordNewUnsubscription(
const PeerSpiffeIdentity& peer) {
std::optional<AuthzConfiguration::SpiffeIdentityMatcher> peer_matcher =
AuthzConfiguration::CreateIdentityMatcherFromPeerSpiffeIdentity(peer);
if (!peer_matcher) {
return absl::InvalidArgumentError(
absl::StrCat("Peer spiffe id '", peer.spiffe_id, "' is malformed"));
}
absl::MutexLock lock(&mutex_);
auto it = peer_to_subscription_count_.find(*peer_matcher);
if (it == peer_to_subscription_count_.end()) {
return absl::OkStatus();
}
it->second--;
if (it->second == 0) {
peer_to_subscription_count_.erase(it);
}
return absl::OkStatus();
}
absl::Status SubscriptionTracker::RecordNewSubscription(
const PeerSpiffeIdentity& peer) {
std::optional<AuthzConfiguration::SpiffeIdentityMatcher> peer_matcher =
AuthzConfiguration::CreateIdentityMatcherFromPeerSpiffeIdentity(peer);
if (!peer_matcher) {
return absl::InvalidArgumentError(
absl::StrCat("Peer spiffe id '", peer.spiffe_id, "' is malformed"));
}
absl::MutexLock lock(&mutex_);
auto it = peer_to_subscription_count_.find(*peer_matcher);
if (it == peer_to_subscription_count_.end()) {
peer_to_subscription_count_.insert({*peer_matcher, 1});
return absl::OkStatus();
}
if (it->second >= universal_subscription_limit_) {
return absl::PermissionDeniedError(absl::Substitute(
"Peer '$0' has reached the limit; the limit is '$1'; currently used "
"'$2'",
peer.DebugString(), universal_subscription_limit_, it->second));
}
it->second++;
return absl::OkStatus();
}
} // namespace milotic::authz