diff --git a/adminapi/src/main/java/io/minio/admin/AddServiceAccountReq.java b/adminapi/src/main/java/io/minio/admin/AddServiceAccountReq.java deleted file mode 100644 index 87120e6f3..000000000 --- a/adminapi/src/main/java/io/minio/admin/AddServiceAccountReq.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, - * (C) 2021 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 javax.annotation.Nullable; - -/** - * add service account request info. - * - *

* @see user-commands.go - */ -@JsonIgnoreProperties(ignoreUnknown = true) -public class AddServiceAccountReq { - @JsonProperty("secretKey") - private String secretKey; - - @JsonProperty("policy") - private byte[] policy; - - @JsonProperty("targetUser") - private String targetUser; - - @JsonProperty("accessKey") - private String accessKey; - - @JsonProperty("name") - private String name; - - @JsonProperty("description") - private String description; - - @JsonProperty("expiration") - private String expiration; - - public AddServiceAccountReq() {} - - public AddServiceAccountReq( - @Nullable @JsonProperty("secretKey") String secretKey, - @Nullable @JsonProperty("policy") byte[] policy, - @Nullable @JsonProperty("targetUser") String targetUser, - @Nullable @JsonProperty("accessKey") String accessKey, - @Nullable @JsonProperty("name") String name, - @Nullable @JsonProperty("description") String description, - @Nullable @JsonProperty("expiration") String expiration) { - this.secretKey = secretKey; - this.policy = policy; - this.targetUser = targetUser; - this.accessKey = accessKey; - this.name = name; - this.description = description; - this.expiration = expiration; - } - - public String secretKey() { - return secretKey; - } - - public byte[] policy() { - return policy; - } - - public String targetUser() { - return targetUser; - } - - public String accessKey() { - return accessKey; - } - - public String description() { - return description; - } - - public String name() { - return name; - } - - public String expiration() { - return expiration; - } -} diff --git a/adminapi/src/main/java/io/minio/admin/ListServiceAccountResp.java b/adminapi/src/main/java/io/minio/admin/ListServiceAccountResp.java index d89d05781..addc940f8 100644 --- a/adminapi/src/main/java/io/minio/admin/ListServiceAccountResp.java +++ b/adminapi/src/main/java/io/minio/admin/ListServiceAccountResp.java @@ -25,9 +25,25 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class ListServiceAccountResp { @JsonProperty("accounts") - private List accounts; + private List accounts; - public List accounts() { + public List accounts() { return accounts; } + + public static class ListServiceAccountInfo { + @JsonProperty("accessKey") + private String accessKey; + + @JsonProperty("expiration") + private String expiration; + + public String expiration() { + return expiration; + } + + public String accessKey() { + return accessKey; + } + } } diff --git a/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java b/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java index 003553e51..622e0e4cd 100644 --- a/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java +++ b/adminapi/src/main/java/io/minio/admin/MinioAdminClient.java @@ -37,6 +37,7 @@ import io.minio.credentials.StaticProvider; import io.minio.http.HttpUtils; import io.minio.http.Method; +import io.minio.messages.ResponseDate; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; @@ -46,14 +47,12 @@ import java.security.InvalidKeyException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; 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.Random; import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -620,6 +619,43 @@ public Message getServerInfo() throws IOException, NoSuchAlgorithmException, Inv } } + private Map buildServiceAccount( + String targetUser, + String name, + String secretKey, + String accessKey, + String newStatus, + String policy, + String description, + boolean updateFlag, + String expiryTime) { + Map serviceAccount = new HashMap<>(7); + if (!updateFlag) { + serviceAccount.put("targetUser", targetUser); + serviceAccount.put("accessKey", accessKey); + } + if (updateFlag && newStatus != null && !newStatus.isEmpty()) { + serviceAccount.put("newStatus", newStatus); + } + if (name != null && !name.isEmpty()) { + serviceAccount.put(updateFlag ? "newName" : "name", name); + } + if (secretKey != null && !secretKey.isEmpty()) { + serviceAccount.put(updateFlag ? "newSecretKey" : "secretKey", secretKey); + } + if (policy != null && !policy.isEmpty()) { + serviceAccount.put( + updateFlag ? "newPolicy" : "policy", policy.getBytes(StandardCharsets.UTF_8)); + } + if (description != null && !description.isEmpty()) { + serviceAccount.put(updateFlag ? "newDescription" : "description", description); + } + if (expiryTime != null && !expiryTime.isEmpty()) { + serviceAccount.put(updateFlag ? "newExpiration" : "expiration", expiryTime); + } + return serviceAccount; + } + /** * Creates a new service account belonging to the user sending. * @@ -650,7 +686,7 @@ public Message getServerInfo() throws IOException, NoSuchAlgorithmException, Inv * @throws IOException thrown to indicate I/O error on MinIO REST operation. * @throws InvalidCipherTextException thrown to indicate data cannot be encrypted/decrypted. */ - public AddServiceAccountReq addServiceAccount( + public Credentials addServiceAccount( @Nonnull String targetUser, @Nullable String name, @Nullable String secretKey, @@ -668,29 +704,27 @@ public AddServiceAccountReq addServiceAccount( if (description != null && description.length() > 256) { throw new IllegalArgumentException("description must be at most 256 bytes long"); } - if (accessKey == null || accessKey.isEmpty()) { - accessKey = generateCredentials(20); - } - if (secretKey == null || secretKey.isEmpty()) { - secretKey = generateCredentials(40); - } - byte[] policyBytes = null; - if (policy != null && !policy.isEmpty()) { - policyBytes = policy.getBytes(StandardCharsets.UTF_8); - } Credentials creds = getCredentials(); - AddServiceAccountReq addServiceAccountReq = - new AddServiceAccountReq( - secretKey, policyBytes, targetUser, accessKey, name, description, expiryTime); try (Response response = execute( Method.PUT, Command.ADD_SERVICE_ACCOUNT, ImmutableMultimap.of("accessKey", accessKey), Crypto.encrypt( - creds.secretKey(), OBJECT_MAPPER.writeValueAsBytes(addServiceAccountReq)))) { - return addServiceAccountReq; + creds.secretKey(), + OBJECT_MAPPER.writeValueAsBytes( + buildServiceAccount( + targetUser, + name, + secretKey, + accessKey, + null, + policy, + description, + false, + expiryTime))))) { + return new Credentials(accessKey, secretKey, null, ResponseDate.fromString(expiryTime)); } } @@ -729,7 +763,7 @@ public void updateServiceAccount( @Nullable String newName, @Nullable String newSecretKey, @Nullable String accessKey, - @Nullable UpdateServiceAccountReq.Status newStatus, + @Nullable String newStatus, @Nullable String newPolicy, @Nullable String newDescription, @Nullable String newExpiration) @@ -741,39 +775,32 @@ public void updateServiceAccount( if (accessKey == null || accessKey.isEmpty()) { throw new IllegalArgumentException("access key must be provided"); } - byte[] policyBytes = null; - if (newPolicy != null && !newPolicy.isEmpty()) { - policyBytes = newPolicy.getBytes(StandardCharsets.UTF_8); + if (newStatus != null + && !newStatus.isEmpty() + && !"on".equals(newStatus) + && !"off".equals(newStatus)) { + throw new IllegalArgumentException("status key must be on or off"); } Credentials creds = getCredentials(); - UpdateServiceAccountReq updateServiceAccountReq = - new UpdateServiceAccountReq( - newSecretKey, policyBytes, newStatus, newName, newDescription, newExpiration); try (Response response = execute( Method.POST, Command.UPDATE_SERVICE_ACCOUNT, ImmutableMultimap.of("accessKey", accessKey), Crypto.encrypt( - creds.secretKey(), OBJECT_MAPPER.writeValueAsBytes(updateServiceAccountReq)))) {} - } - - /** - * Creates randomly generated credentials of maximum. - * - * @param length credentials length - * @return credential - */ - private String generateCredentials(int length) { - String characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - StringBuffer randomString = new StringBuffer(); - Random random = new Random(new SecureRandom().nextLong()); - for (int i = 0; i < length; i++) { - int randomIndex = random.nextInt(length); - randomString.append(characters.charAt(randomIndex % characters.length())); - } - return randomString.toString(); + creds.secretKey(), + OBJECT_MAPPER.writeValueAsBytes( + buildServiceAccount( + null, + newName, + newSecretKey, + accessKey, + newStatus, + newPolicy, + newDescription, + true, + newExpiration))))) {} } /** @@ -808,7 +835,7 @@ public void deleteServiceAccount(@Nonnull String accessKey) * @throws IOException thrown to indicate I/O error on MinIO REST operation. * @throws InvalidCipherTextException thrown to indicate data cannot be encrypted/decrypted. */ - public List listServiceAccount(@Nonnull String userName) + public ListServiceAccountResp listServiceAccount(@Nonnull String userName) throws NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidCipherTextException { if (userName == null || userName.isEmpty()) { @@ -823,7 +850,7 @@ public List listServiceAccount(@Nonnull String userName) null)) { Credentials creds = getCredentials(); byte[] jsonData = Crypto.decrypt(creds.secretKey(), response.body().bytes()); - return OBJECT_MAPPER.readValue(jsonData, ListServiceAccountResp.class).accounts(); + return OBJECT_MAPPER.readValue(jsonData, ListServiceAccountResp.class); } } diff --git a/adminapi/src/main/java/io/minio/admin/UpdateServiceAccountReq.java b/adminapi/src/main/java/io/minio/admin/UpdateServiceAccountReq.java deleted file mode 100644 index 89dc497f0..000000000 --- a/adminapi/src/main/java/io/minio/admin/UpdateServiceAccountReq.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, - * (C) 2021 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.JsonCreator; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonValue; -import javax.annotation.Nullable; - -/** - * add service account request info. - * - *

* @see user-commands.go - */ -@JsonIgnoreProperties(ignoreUnknown = true) -public class UpdateServiceAccountReq { - @JsonProperty("newSecretKey") - private String newSecretKey; - - @JsonProperty("newStatus") - private Status newStatus; - - @JsonProperty("newPolicy") - private byte[] newPolicy; - - @JsonProperty("newName") - private String newName; - - @JsonProperty("newDescription") - private String newDescription; - - @JsonProperty("newExpiration") - private String newExpiration; - - public UpdateServiceAccountReq() {} - - public UpdateServiceAccountReq( - @Nullable @JsonProperty("newSecretKey") String newSecretKey, - @Nullable @JsonProperty("newPolicy") byte[] newPolicy, - @Nullable @JsonProperty("newStatus") Status newStatus, - @Nullable @JsonProperty("newName") String newName, - @Nullable @JsonProperty("newDescription") String newDescription, - @Nullable @JsonProperty("newExpiration") String newExpiration) { - this.newSecretKey = newSecretKey; - this.newPolicy = newPolicy; - this.newStatus = newStatus; - this.newName = newName; - this.newDescription = newDescription; - this.newExpiration = newExpiration; - } - - public String newSecretKey() { - return newSecretKey; - } - - public byte[] newPolicy() { - return newPolicy; - } - - public Status newStatus() { - return newStatus; - } - - public String newName() { - return newName; - } - - public String newDescription() { - return newDescription; - } - - public String newExpiration() { - return newExpiration; - } - - public static enum Status { - ENABLED("on"), - DISABLED("off"); - - private final String value; - - private Status(String value) { - this.value = value; - } - - @JsonValue - public String toString() { - return this.value; - } - - @JsonCreator - public static UpdateServiceAccountReq.Status fromString(String statusString) { - if ("on".equals(statusString)) { - return ENABLED; - } - - if ("off".equals(statusString)) { - return DISABLED; - } - - if (statusString.isEmpty()) { - return null; - } - - throw new IllegalArgumentException("Unknown status " + statusString); - } - } -}