Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMR-9266 refactors permission acl filtering #1926

Merged
merged 2 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 58 additions & 20 deletions access-control-app/src/cmr/access_control/services/acl_service.clj
Original file line number Diff line number Diff line change
Expand Up @@ -237,58 +237,96 @@
[acl]
(-> acl :provider-identity :target (= schema/ingest-management-acl-target)))

(defn- concept-permissions-granted-by-acls
(defn-timed concept-permissions-granted-by-acls
"Returns the set of permission keywords (:read, :order, and :update) granted on concept
to the seq of group guids by seq of acls."
[concept sids acls]
(let [provider-acls (filter #(provider-acl? (:provider-id concept) %) acls)
(let [[catalog-item-acls ingest-management-acls] acls
provider-id (:provider-id concept)
;; When a user has UPDATE on the provider's INGEST_MANAGEMENT_ACL target, then they have UPDATE and
;; DELETE permission on all of the provider's catalog items.
ingest-management-permissions (when (some #(acl/acl-matches-sids-and-permission? sids "update" %)
(filter ingest-management-acl? provider-acls))
(get ingest-management-acls provider-id))
[:update :delete])
;; The remaining catalog item ACLs can only grant READ or ORDER permission.
catalog-item-acls (filter :catalog-item-identity provider-acls)
catalog-item-permissions (for [permission [:read :order]
:when (some #(grants-concept-permission? % permission concept sids)
catalog-item-acls)]
(get catalog-item-acls provider-id))]
permission)]
(set
(concat catalog-item-permissions
ingest-management-permissions))))

(defn- add-acl-enforcement-fields
(defn- enforcement-fields-applicable?
"Checks provider catalog-item acls for granule concept to confirm if any acls apply temporal or access-value restrictions."
[concept acls]
(if (:deleted concept)
false
(some #(as-> % value
(:catalog-item-identity value)
(select-keys value [:granule-identifier :collection-identifier])
(vals value)
(mapcat keys value)
(some #{:access-value :temporal} value))
(get (first acls) (:provider-id concept)))))

(defn-timed add-acl-enforcement-fields
"Adds all fields necessary for comparing concept map against ACLs."
[context concept]
(let [concept (acl-matchers/add-acl-enforcement-fields-to-concept context concept)]
[context concept acls]
(let [concept (acl-matchers/add-acl-enforcement-fields-to-concept context
;; If no acls exist in the provider that govern enforcement fields,
;; set deleted to true to avoid parsing the granule metadata
(assoc concept :deleted (not (enforcement-fields-applicable? concept acls))))]
(if-let [parent-collection (:parent-collection concept)]
(assoc concept :parent-collection
(acl-matchers/add-acl-enforcement-fields-to-concept
context parent-collection))
concept)))

(defn add-parent-collection-to-concept
(-> concept
(assoc :parent-collection
(acl-matchers/add-acl-enforcement-fields-to-concept
context parent-collection))
(dissoc :metadata))
(dissoc concept :metadata))))

(defn-timed add-parent-collection-to-concept
[concept parent-concepts]
(let [parent-id (get-in concept [:extra-fields :parent-collection-id])
parent (first (filter #(= parent-id (:concept-id %)) parent-concepts))]
(assoc concept :parent-collection parent)))

(defn- prepare-permission-acls
"Group acls by provider, return catalog-item acl and ingest management acl maps seperately. We do this to avoid
filtering the same list of acls repeatidly for permission requests related to large granule count orders of the same provider."
[acls]
(let [provider-acls (group-by (fn [acl]
(or (get-in acl [:catalog-item-identity :provider-id])
(get-in acl [:provider-identity :provider-id])))
acls)
catalog-item-acls (reduce
(fn [provider-map provider]
(assoc provider-map provider (filter :catalog-item-identity (get provider-map provider))))
provider-acls
(keys provider-acls))
ingest-management-acls (reduce
(fn [provider-map provider]
(assoc provider-map provider (filter ingest-management-acl? (get provider-map provider))))
provider-acls
(keys provider-acls))]
[catalog-item-acls ingest-management-acls]))

(defn-timed get-catalog-item-permissions
"Returns a map of concept ids to seqs of permissions granted on that concept for the given username."
[context username-or-type concept-ids]
(let [sids (auth-util/get-sids context username-or-type)
acls (concat
(acl-util/get-acl-concepts-by-identity-type-and-target
context index/provider-identity-type-name schema/ingest-management-acl-target)
(acl-util/get-acl-concepts-by-identity-type-and-target
context index/catalog-item-identity-type-name nil))
acls (prepare-permission-acls (concat
(acl-util/get-acl-concepts-by-identity-type-and-target
context index/provider-identity-type-name schema/ingest-management-acl-target)
(acl-util/get-acl-concepts-by-identity-type-and-target
context index/catalog-item-identity-type-name nil)))
concepts (mdb1/get-latest-concepts context (distinct concept-ids))
parent-concepts (mdb1/get-latest-concepts context (distinct (remove nil? (map #(get-in % [:extra-fields :parent-collection-id]) concepts))))
concepts-with-parents (map #(add-parent-collection-to-concept % parent-concepts) concepts)]

(into {}
(for [concept concepts-with-parents
:let [concept-with-acl-fields (add-acl-enforcement-fields context concept)]]
:let [concept-with-acl-fields (add-acl-enforcement-fields context concept acls)]]
[(:concept-id concept)
(concept-permissions-granted-by-acls concept-with-acl-fields sids acls)]))))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@
(let [containers (:containers this)
^FixedHostPortGenericContainer node (:elasticsearch containers)
^FixedHostPortGenericContainer kibana (:kibana containers)]
(.stop node)
(when node
(.stop node))
(when-let [data-dir (get-in this [:opts :data-dir])]
(util/delete-recursively (:data-dir this)))
(when kibana
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

(stop
[this system]
(let [redis (:redis this)]
(when-let [redis (:redis this)]
(.stop redis))))

(defn create-redis-server
Expand Down
16 changes: 11 additions & 5 deletions umm-spec-lib/src/cmr/umm_spec/acl_matchers.clj
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
[clojure.string :as str]
[cmr.acl.core :as acl-core]
[cmr.common.cache :as cache]
[cmr.common.cache.in-memory-cache :as mem-cache]
[cmr.common.cache.cache-spec :as cache-spec]
[cmr.common.cache.in-memory-cache :as mem-cache]
[cmr.common.log :refer [info debug warn error]]
[cmr.common.services.errors :as errors]
[cmr.common.time-keeper :as tk]
[cmr.common.util :as u :refer [update-in-each]]
Expand Down Expand Up @@ -181,10 +182,15 @@

(defmethod add-acl-enforcement-fields-to-concept :granule
[context concept]
(-> concept
(u/lazy-assoc :access-value (legacy/parse-concept-access-value concept))
(u/lazy-assoc :temporal (legacy/parse-concept-temporal concept))
(assoc :collection-concept-id (get-in concept [:extra-fields :parent-collection-id]))))
(let [deleted? (:deleted concept)]
(as-> concept concept
(if-not deleted?
(u/lazy-assoc concept :access-value (legacy/parse-concept-access-value concept))
concept)
(if-not deleted?
(u/lazy-assoc concept :temporal (legacy/parse-concept-temporal concept))
concept)
(assoc concept :collection-concept-id (get-in concept [:extra-fields :parent-collection-id])))))

(defn add-acl-enforcement-fields
"Adds the fields necessary to enforce ACLs to the concepts."
Expand Down