Skip to content

MinioAdmin: allow specifying policies as dict besides file #1480

New issue

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

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

Already on GitHub? # to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

Alveel
Copy link
Contributor

@Alveel Alveel commented Jan 31, 2025

It would be nice to be able to add/update IAM/service account policies through Python dict objects as well as what's currently available through JSON files.

This PR tries to accomplish this.

Feedback/questions welcome.

Depends on #1483

@darix
Copy link

darix commented Feb 4, 2025

i wonder if it makes sense to refactor out something like

def _load_policy(policy_file, policy):
        if policy and policy_file:
            raise ValueError(
                "only one of policy or policy_file may be specified")
        if not policy or not policy_file:
            raise ValueError("either policy or policy_file must be specified")
        body = ''
        if policy:
            body = json.dumps(policy)
        elif policy_file:
            with open(policy_file, encoding='utf-8') as file:
                body = file.read()
       return body

given in how many places we basically have the same code now.

@Alveel
Copy link
Contributor Author

Alveel commented Feb 4, 2025

Sounds fairly sensible actually. I'll wait for feedback from a member and see what they think.

@Alveel
Copy link
Contributor Author

Alveel commented Feb 11, 2025

@balamurugana please review

@Alveel
Copy link
Contributor Author

Alveel commented Feb 13, 2025

I'd love to hear some feedback on the current state.

@Alveel Alveel requested a review from balamurugana February 13, 2025 21:01
@harshavardhana harshavardhana requested review from balamurugana and removed request for balamurugana February 14, 2025 10:35
@harshavardhana
Copy link
Member

I'd love to hear some feedback on the current state.

Please fix the CI tests

@Alveel
Copy link
Contributor Author

Alveel commented Feb 14, 2025

Fixed. Moved the .open() for Path to its own line so I can put the mypy comment on the same line while keeping it within 80 characters to keep autopep8 happy.

Copy link
Member

@balamurugana balamurugana left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below is the exact diff, I am referring

diff --git a/minio/minioadmin.py b/minio/minioadmin.py
index d62ac21..0fd2979 100644
--- a/minio/minioadmin.py
+++ b/minio/minioadmin.py
@@ -452,16 +452,24 @@ class MinioAdmin:
         response = self._url_open("GET", _COMMAND.LIST_GROUPS)
         return response.data.decode()
 
-    def policy_add(self, policy_name: str, policy_file: str) -> str:
+    def policy_add(self,
+                   policy_name: str,
+                   policy_file: str | None = None,
+                   policy: bytes | None = None) -> str:
         """Add new policy."""
-        with open(policy_file, encoding='utf-8') as file:
-            response = self._url_open(
-                "PUT",
-                _COMMAND.ADD_CANNED_POLICY,
-                query_params={"name": policy_name},
-                body=file.read().encode(),
-            )
-            return response.data.decode()
+        if not (policy_file is not None) ^ (policy is not None):
+            raise ValueError("either policy_file or policy must be provided")
+        body = policy
+        if policy_file:
+            with open(policy_file, encoding='utf-8') as file:
+                body = file.read().encode()
+        response = self._url_open(
+            "PUT",
+            _COMMAND.ADD_CANNED_POLICY,
+            query_params={"name": policy_name},
+            body=body,
+        )
+        return response.data.decode()
 
     def policy_remove(self, policy_name: str) -> str:
         """Remove policy."""
@@ -754,6 +762,7 @@ class MinioAdmin:
                             name: str | None = None,
                             description: str | None = None,
                             policy_file: str | None = None,
+                            policy: dict | None = None,
                             expiration: str | None = None,
                             status: str | None = None) -> str:
         """
@@ -763,7 +772,9 @@ class MinioAdmin:
             raise ValueError("both access key and secret key must be provided")
         if access_key == "" or secret_key == "":
             raise ValueError("access key or secret key must not be empty")
-        data = {
+        if policy_file is not None and policy is not None:
+            raise ValueError("either policy_file or policy must be provided")
+        data: dict[str, Any] = {
             "status": "enabled",
             "accessKey": access_key,
             "secretKey": secret_key,
@@ -775,6 +786,8 @@ class MinioAdmin:
         if policy_file:
             with open(policy_file, encoding="utf-8") as file:
                 data["policy"] = json.load(file)
+        if policy:
+            data["policy"] = policy
         if expiration:
             data["expiration"] = expiration
         if status:
@@ -798,15 +811,19 @@ class MinioAdmin:
                                name: str | None = None,
                                description: str | None = None,
                                policy_file: str | None = None,
+                               policy: dict | None = None,
                                expiration: str | None = None,
                                status: str | None = None) -> str:
         """Update an existing service account"""
-        args = [secret_key, name, description, policy_file, expiration, status]
+        args = [secret_key, name, description,
+                policy_file, policy, expiration, status]
         if not any(arg for arg in args):
             raise ValueError("at least one of secret_key, name, description, "
                              "policy_file, expiration or status must be "
                              "specified")
-        data = {}
+        if policy_file is not None and policy is not None:
+            raise ValueError("either policy_file or policy must be provided")
+        data: dict[str, Any] = {}
         if secret_key:
             data["newSecretKey"] = secret_key
         if name:
@@ -816,6 +833,8 @@ class MinioAdmin:
         if policy_file:
             with open(policy_file, encoding="utf-8") as file:
                 data["newPolicy"] = json.load(file)
+        if policy:
+            data["newPolicy"] = policy
         if expiration:
             data["newExpiration"] = expiration
         if status:

@Alveel
Copy link
Contributor Author

Alveel commented Feb 18, 2025

I think that's it? I still see "1 requested change" but I don't see where or what it is.

Do you want me to squash my commits?

@Alveel
Copy link
Contributor Author

Alveel commented Feb 20, 2025

@balamurugana can you take a look? 🙂

@Alveel
Copy link
Contributor Author

Alveel commented Feb 25, 2025

Apologies, that was a dumb error I introduced and insufficiently tested. Tested properly now and passing all tests.

@Alveel Alveel force-pushed the allow-specifying-policy-as-dict branch from 62bb83b to 98b71fa Compare February 26, 2025 15:04
@Alveel
Copy link
Contributor Author

Alveel commented Feb 26, 2025

Squashed commits, should be all clean now. Can you please take a look?

If needed, I still have the original commits in a separate branch locally.

balamurugana
balamurugana previously approved these changes Feb 27, 2025
Copy link
Member

@balamurugana balamurugana left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on #1483

@balamurugana balamurugana marked this pull request as draft February 27, 2025 04:33
@Alveel Alveel marked this pull request as ready for review April 17, 2025 14:42
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants