| #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 |