From 0f64fc83d9972c2e702089dcfd2d321d70bc1b80 Mon Sep 17 00:00:00 2001 From: jongmin-chung Date: Thu, 13 Feb 2025 15:42:49 +0900 Subject: [PATCH 1/3] Add attach or detach policies --- .../io/minio/admin/AttachPoliciesResp.java | 51 +++++++++++ .../io/minio/admin/DetachPoliciesResp.java | 51 +++++++++++ .../java/io/minio/admin/MinioAdminClient.java | 89 ++++++++++++++++++- 3 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 adminapi/src/main/java/io/minio/admin/AttachPoliciesResp.java create mode 100644 adminapi/src/main/java/io/minio/admin/DetachPoliciesResp.java diff --git a/adminapi/src/main/java/io/minio/admin/AttachPoliciesResp.java b/adminapi/src/main/java/io/minio/admin/AttachPoliciesResp.java new file mode 100644 index 000000000..6c1770a51 --- /dev/null +++ b/adminapi/src/main/java/io/minio/admin/AttachPoliciesResp.java @@ -0,0 +1,51 @@ +/* + * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, + * (C) 2022 MinIO, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.minio.admin; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.LocalDateTime; +import java.util.Arrays; + +/** Represents detachPolicies information. */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class AttachPoliciesResp { + @JsonProperty("policiesAttached") + private String[] policiesAttached; + + @JsonProperty("updatedAt") + private LocalDateTime updatedAt; + + public String[] getPoliciesAttached() { + return policiesAttached; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + @Override + public String toString() { + return "AttachPoliciesResp{" + + "policiesAttached=" + + Arrays.toString(policiesAttached) + + ", updatedAt=" + + updatedAt + + '}'; + } +} diff --git a/adminapi/src/main/java/io/minio/admin/DetachPoliciesResp.java b/adminapi/src/main/java/io/minio/admin/DetachPoliciesResp.java new file mode 100644 index 000000000..2b341d18a --- /dev/null +++ b/adminapi/src/main/java/io/minio/admin/DetachPoliciesResp.java @@ -0,0 +1,51 @@ +/* + * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, + * (C) 2022 MinIO, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.minio.admin; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.LocalDateTime; +import java.util.*; + +/** Represents detachPolicies information. */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class DetachPoliciesResp { + @JsonProperty("policiesDetached") + private String[] policiesDetached; + + @JsonProperty("updatedAt") + private LocalDateTime updatedAt; + + public String[] getPoliciesDetached() { + return policiesDetached; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + @Override + public String toString() { + return "DetachPoliciesResp{" + + "policiesDetached=" + + Arrays.toString(policiesDetached) + + ", updatedAt=" + + updatedAt + + '}'; + } +} diff --git a/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java b/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java index de11bd275..06c93289a 100644 --- a/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java +++ b/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java @@ -89,7 +89,10 @@ private enum Command { UPDATE_SERVICE_ACCOUNT("update-service-account"), LIST_SERVICE_ACCOUNTS("list-service-accounts"), DELETE_SERVICE_ACCOUNT("delete-service-account"), - INFO_SERVICE_ACCOUNT("info-service-account"); + INFO_SERVICE_ACCOUNT("info-service-account"), + ATTACH_POLICIES("idp/builtin/policy/attach"), + DETACH_POLICIES("idp/builtin/policy/detach"), + ; private final String value; private Command(String value) { @@ -843,6 +846,90 @@ public GetServiceAccountInfoResp getServiceAccountInfo(@Nonnull String accessKey } } + /** + * Attach multiple policies to a user or group.
+ * + *

Throws a runtime exception with the error code "XMinioAdminPolicyChangeAlreadyApplied" and + * message "The specified policy change is already in effect." if there is no difference between + * the policies before and after the change. + * + * @param userOrGroupName User or Group name. + * @param isGroup Flag to denote if userOrGroupName is a group name. + * @param policyNames Array of policy names to be attached. + * @throws NoSuchAlgorithmException Thrown to indicate missing of MD5 or SHA-256 digest library. + * @throws InvalidKeyException Thrown to indicate missing of HMAC SHA-256 library. + * @throws IOException Thrown to indicate I/O error on MinIO REST operation. + */ + public AttachPoliciesResp attachPolicies( + @Nullable String userOrGroupName, boolean isGroup, String[] policyNames) + throws NoSuchAlgorithmException, InvalidKeyException, IOException, + InvalidCipherTextException { + if (userOrGroupName == null || userOrGroupName.isEmpty()) { + throw new IllegalArgumentException("user/group name must be provided"); + } + + Map policyEntity = new HashMap<>(); + if (isGroup) { + policyEntity.put("group", userOrGroupName); + } else { + policyEntity.put("user", userOrGroupName); + } + policyEntity.put("policies", policyNames); + + Credentials creds = getCredentials(); + try (Response response = + execute( + Method.POST, + Command.ATTACH_POLICIES, + null, + Crypto.encrypt(OBJECT_MAPPER.writeValueAsBytes(policyEntity), creds.secretKey()))) { + byte[] jsonData = Crypto.decrypt(response.body().byteStream(), creds.secretKey()); + return OBJECT_MAPPER.readValue(jsonData, AttachPoliciesResp.class); + } + } + + /** + * Detach multiple policies to a user or group.
+ * + *

Throws a runtime exception with the error code "XMinioAdminPolicyChangeAlreadyApplied" and + * message "The specified policy change is already in effect." if there is no difference between + * the policies before and after the change. + * + * @param userOrGroupName User or Group name. + * @param isGroup Flag to denote if userOrGroupName is a group name. + * @param policyNames Array of policy names to be attached. + * @throws NoSuchAlgorithmException Thrown to indicate missing of MD5 or SHA-256 digest library. + * @throws InvalidKeyException Thrown to indicate missing of HMAC SHA-256 library. + * @throws IOException Thrown to indicate I/O error on MinIO REST operation. + */ + public DetachPoliciesResp detachPolicies( + @Nullable String userOrGroupName, boolean isGroup, String[] policyNames) + throws NoSuchAlgorithmException, InvalidKeyException, IOException, + InvalidCipherTextException { + if (userOrGroupName == null || userOrGroupName.isEmpty()) { + throw new IllegalArgumentException("user/group name must be provided"); + } + + Map policyEntity = new HashMap<>(); + if (isGroup) { + policyEntity.put("group", userOrGroupName); + } else { + policyEntity.put("user", userOrGroupName); + } + policyEntity.put("policies", policyNames); + + Credentials creds = getCredentials(); + try (Response response = + execute( + Method.POST, + Command.DETACH_POLICIES, + null, + Crypto.encrypt(OBJECT_MAPPER.writeValueAsBytes(policyEntity), creds.secretKey()))) { + byte[] jsonData = Crypto.decrypt(response.body().byteStream(), creds.secretKey()); + return OBJECT_MAPPER.readValue(jsonData, DetachPoliciesResp.class); + } + } + /** * Sets HTTP connect, write and read timeouts. A value of 0 means no timeout, otherwise values * must be between 1 and Integer.MAX_VALUE when converted to milliseconds. From de7999862c322385b3f4bf00dfbd58209f6da5ed Mon Sep 17 00:00:00 2001 From: jongmin-chung Date: Mon, 17 Feb 2025 10:23:34 +0900 Subject: [PATCH 2/3] Refactor minio-py style --- .../java/io/minio/admin/MinioAdminClient.java | 93 +++++++------------ 1 file changed, 34 insertions(+), 59 deletions(-) diff --git a/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java b/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java index 06c93289a..9b59e13dd 100644 --- a/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java +++ b/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java @@ -49,11 +49,7 @@ import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; import javax.annotation.Nonnull; @@ -90,8 +86,8 @@ private enum Command { LIST_SERVICE_ACCOUNTS("list-service-accounts"), DELETE_SERVICE_ACCOUNT("delete-service-account"), INFO_SERVICE_ACCOUNT("info-service-account"), - ATTACH_POLICIES("idp/builtin/policy/attach"), - DETACH_POLICIES("idp/builtin/policy/detach"), + IDP_BUILTIN_POLICY_ATTACH("idp/builtin/policy/attach"), + IDP_BUILTIN_POLICY_DETACH("idp/builtin/policy/detach"), ; private final String value; @@ -847,87 +843,66 @@ public GetServiceAccountInfoResp getServiceAccountInfo(@Nonnull String accessKey } /** - * Attach multiple policies to a user or group.
+ * Attach or Detach multiple policies to a user or group.
* *

Throws a runtime exception with the error code "XMinioAdminPolicyChangeAlreadyApplied" and * message "The specified policy change is already in effect." if there is no difference between * the policies before and after the change. * - * @param userOrGroupName User or Group name. - * @param isGroup Flag to denote if userOrGroupName is a group name. - * @param policyNames Array of policy names to be attached. + * @param command Command to be executed. + * @param polices Array of policy names to be attached. + * @param user User name. + * @param group Group name. * @throws NoSuchAlgorithmException Thrown to indicate missing of MD5 or SHA-256 digest library. * @throws InvalidKeyException Thrown to indicate missing of HMAC SHA-256 library. * @throws IOException Thrown to indicate I/O error on MinIO REST operation. */ - public AttachPoliciesResp attachPolicies( - @Nullable String userOrGroupName, boolean isGroup, String[] policyNames) + private byte[] attachDetachPolicy( + Command command, List polices, @Nullable String user, @Nullable String group) throws NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidCipherTextException { - if (userOrGroupName == null || userOrGroupName.isEmpty()) { - throw new IllegalArgumentException("user/group name must be provided"); + + if (user == null && group == null) { + throw new IllegalArgumentException("user or group must be provided"); } Map policyEntity = new HashMap<>(); - if (isGroup) { - policyEntity.put("group", userOrGroupName); + policyEntity.put("policies", polices); + if (user != null) { + policyEntity.put("user", user); } else { - policyEntity.put("user", userOrGroupName); + policyEntity.put("group", group); } - policyEntity.put("policies", policyNames); Credentials creds = getCredentials(); try (Response response = execute( Method.POST, - Command.ATTACH_POLICIES, + command, null, Crypto.encrypt(OBJECT_MAPPER.writeValueAsBytes(policyEntity), creds.secretKey()))) { - byte[] jsonData = Crypto.decrypt(response.body().byteStream(), creds.secretKey()); - return OBJECT_MAPPER.readValue(jsonData, AttachPoliciesResp.class); + return Crypto.decrypt(response.body().byteStream(), creds.secretKey()); } } - /** - * Detach multiple policies to a user or group.
- * - *

Throws a runtime exception with the error code "XMinioAdminPolicyChangeAlreadyApplied" and - * message "The specified policy change is already in effect." if there is no difference between - * the policies before and after the change. - * - * @param userOrGroupName User or Group name. - * @param isGroup Flag to denote if userOrGroupName is a group name. - * @param policyNames Array of policy names to be attached. - * @throws NoSuchAlgorithmException Thrown to indicate missing of MD5 or SHA-256 digest library. - * @throws InvalidKeyException Thrown to indicate missing of HMAC SHA-256 library. - * @throws IOException Thrown to indicate I/O error on MinIO REST operation. - */ - public DetachPoliciesResp detachPolicies( - @Nullable String userOrGroupName, boolean isGroup, String[] policyNames) + /** Attach multiple policies to a user or group. */ + public AttachPoliciesResp attachPolicy( + List policies, @Nullable String user, @Nullable String group) throws NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidCipherTextException { - if (userOrGroupName == null || userOrGroupName.isEmpty()) { - throw new IllegalArgumentException("user/group name must be provided"); - } - - Map policyEntity = new HashMap<>(); - if (isGroup) { - policyEntity.put("group", userOrGroupName); - } else { - policyEntity.put("user", userOrGroupName); - } - policyEntity.put("policies", policyNames); + byte[] result = + this.attachDetachPolicy(Command.IDP_BUILTIN_POLICY_ATTACH, policies, user, group); + return OBJECT_MAPPER.readValue(result, AttachPoliciesResp.class); + } - Credentials creds = getCredentials(); - try (Response response = - execute( - Method.POST, - Command.DETACH_POLICIES, - null, - Crypto.encrypt(OBJECT_MAPPER.writeValueAsBytes(policyEntity), creds.secretKey()))) { - byte[] jsonData = Crypto.decrypt(response.body().byteStream(), creds.secretKey()); - return OBJECT_MAPPER.readValue(jsonData, DetachPoliciesResp.class); - } + /** Detach multiple policies to a user or group. */ + public DetachPoliciesResp detachPolicy( + List policies, @Nullable String user, @Nullable String group) + throws NoSuchAlgorithmException, InvalidKeyException, IOException, + InvalidCipherTextException { + byte[] result = + this.attachDetachPolicy(Command.IDP_BUILTIN_POLICY_DETACH, policies, user, group); + return OBJECT_MAPPER.readValue(result, DetachPoliciesResp.class); } /** From f2beac843f81b9d0d3cc3e33df07fcca3cafa780 Mon Sep 17 00:00:00 2001 From: jongmin-chung Date: Mon, 17 Feb 2025 10:27:20 +0900 Subject: [PATCH 3/3] Add nonnull parameter --- .../src/main/java/io/minio/admin/MinioAdminClient.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java b/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java index 9b59e13dd..fb9768288 100644 --- a/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java +++ b/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java @@ -858,7 +858,10 @@ public GetServiceAccountInfoResp getServiceAccountInfo(@Nonnull String accessKey * @throws IOException Thrown to indicate I/O error on MinIO REST operation. */ private byte[] attachDetachPolicy( - Command command, List polices, @Nullable String user, @Nullable String group) + @Nonnull Command command, + @Nonnull List polices, + @Nullable String user, + @Nullable String group) throws NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidCipherTextException { @@ -887,7 +890,7 @@ private byte[] attachDetachPolicy( /** Attach multiple policies to a user or group. */ public AttachPoliciesResp attachPolicy( - List policies, @Nullable String user, @Nullable String group) + @Nonnull List policies, @Nullable String user, @Nullable String group) throws NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidCipherTextException { byte[] result = @@ -897,7 +900,7 @@ public AttachPoliciesResp attachPolicy( /** Detach multiple policies to a user or group. */ public DetachPoliciesResp detachPolicy( - List policies, @Nullable String user, @Nullable String group) + @Nonnull List policies, @Nullable String user, @Nullable String group) throws NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidCipherTextException { byte[] result =