diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubClient.java b/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubClient.java index a623f76..6983cf5 100644 --- a/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubClient.java +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubClient.java @@ -22,7 +22,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.springframework.credhub.support.JsonUtils; +import org.springframework.credhub.support.utils.JsonUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; import org.springframework.http.MediaType; diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubOperations.java b/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubOperations.java index 8e81b83..faaaabd 100644 --- a/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubOperations.java +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubOperations.java @@ -18,6 +18,8 @@ package org.springframework.credhub.core; import java.util.List; +import org.springframework.credhub.support.permissions.Actor; +import org.springframework.credhub.support.permissions.CredentialPermission; import org.springframework.credhub.support.CredentialDetails; import org.springframework.credhub.support.CredentialName; import org.springframework.credhub.support.CredentialSummary; @@ -65,17 +67,6 @@ public interface CredHubOperations { */ CredentialDetails getById(final String id, Class credentialType); - /** - * Retrieve a credential using its name, as passed to a write request. - * Only the current credential value will be returned. - * - * @param name the name of the credential; must not be {@literal null} - * @param credentialType the type of credential expected to be returned - * @param the credential implementation type - * @return the details of the retrieved credential - */ - CredentialDetails getByName(final String name, Class credentialType); - /** * Retrieve a credential using its name, as passed to a write request. * Only the current credential value will be returned. @@ -87,18 +78,6 @@ public interface CredHubOperations { */ CredentialDetails getByName(final CredentialName name, Class credentialType); - /** - * Retrieve a credential using its name, as passed to a write request. - * A collection of all stored values for the named credential will be returned, - * including historical values. - * - * @param name the name of the credential; must not be {@literal null} - * @param credentialType the type of credential expected to be returned - * @param the credential implementation type - * @return the details of the retrieved credential, including history - */ - List> getByNameWithHistory(String name, Class credentialType); - /** * Retrieve a credential using its name, as passed to a write request. * A collection of all stored values for the named credential will be returned, @@ -111,14 +90,6 @@ public interface CredHubOperations { */ List> getByNameWithHistory(CredentialName name, Class credentialType); - /** - * Find a credential using a full or partial name. - * - * @param name the name of the credential; must not be {@literal null} - * @return a summary of the credential search results - */ - List findByName(String name); - /** * Find a credential using a full or partial name. * @@ -140,14 +111,32 @@ public interface CredHubOperations { * * @param name the name of the credential; must not be {@literal null} */ - void deleteByName(String name); + void deleteByName(CredentialName name); /** - * Delete a credential by its full name. + * Get the permissions associated with a credential. * * @param name the name of the credential; must not be {@literal null} + * @return the collection of permissions associated with the credential */ - void deleteByName(CredentialName name); + List getPermissions(CredentialName name); + + /** + * Add permissions to an existing credential. + * + * @param name the name of the credential; must not be {@literal null} + * @param permissions a collection of permissions to add + * @return the collection of permissions associated with the credential + */ + List addPermissions(CredentialName name, CredentialPermission... permissions); + + /** + * Delete a permission associated with a credential. + * + * @param name the name of the credential; must not be {@literal null} + * @param actor the actor of the permission; must not be {@literal null} + */ + void deletePermission(CredentialName name, Actor actor); /** * Search the provided data structure of bound service credentials, looking for diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubTemplate.java b/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubTemplate.java index 2364d76..ce4677b 100644 --- a/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubTemplate.java +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubTemplate.java @@ -22,11 +22,14 @@ import org.springframework.core.ParameterizedTypeReference; import org.springframework.credhub.support.CredentialDetails; import org.springframework.credhub.support.CredentialDetailsData; import org.springframework.credhub.support.CredentialName; +import org.springframework.credhub.support.CredentialPermissions; +import org.springframework.credhub.support.CredentialRequest; import org.springframework.credhub.support.CredentialSummary; import org.springframework.credhub.support.CredentialSummaryData; import org.springframework.credhub.support.ParametersRequest; import org.springframework.credhub.support.ServicesData; -import org.springframework.credhub.support.CredentialRequest; +import org.springframework.credhub.support.permissions.Actor; +import org.springframework.credhub.support.permissions.CredentialPermission; import org.springframework.http.HttpEntity; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -53,6 +56,11 @@ public class CredHubTemplate implements CredHubOperations { static final String NAME_URL_QUERY_CURRENT = NAME_URL_QUERY + "¤t=true"; static final String NAME_LIKE_URL_QUERY = BASE_URL_PATH + "?name-like={name}"; static final String PATH_URL_QUERY = BASE_URL_PATH + "?path={path}"; + + static final String PERMISSIONS_URL_PATH = "/api/v1/permissions"; + static final String PERMISSIONS_URL_QUERY = PERMISSIONS_URL_PATH + "?credential_name={name}"; + static final String PERMISSIONS_ACTOR_URL_QUERY = PERMISSIONS_URL_QUERY + "&actor={actor}"; + static final String INTERPOLATE_URL_PATH = "/api/v1/interpolate"; private final RestTemplate restTemplate; @@ -152,7 +160,7 @@ public class CredHubTemplate implements CredHubOperations { } @Override - public CredentialDetails getByName(final String name, Class credentialType) { + public CredentialDetails getByName(final CredentialName name, Class credentialType) { Assert.notNull(name, "credential name must not be null"); Assert.notNull(credentialType, "credential type must not be null"); @@ -163,7 +171,7 @@ public class CredHubTemplate implements CredHubOperations { @Override public CredentialDetails doWithRestOperations(RestOperations restOperations) { ResponseEntity> response = - restOperations.exchange(NAME_URL_QUERY_CURRENT, GET, null, ref, name); + restOperations.exchange(NAME_URL_QUERY_CURRENT, GET, null, ref, name.getName()); throwExceptionOnError(response); @@ -173,14 +181,7 @@ public class CredHubTemplate implements CredHubOperations { } @Override - public CredentialDetails getByName(final CredentialName name, Class credentialType) { - Assert.notNull(name, "credential name must not be null"); - - return getByName(name.getName(), credentialType); - } - - @Override - public List> getByNameWithHistory(final String name, Class credentialType) { + public List> getByNameWithHistory(final CredentialName name, Class credentialType) { Assert.notNull(name, "credential name must not be null"); Assert.notNull(credentialType, "credential type must not be null"); @@ -191,7 +192,7 @@ public class CredHubTemplate implements CredHubOperations { @Override public List> doWithRestOperations(RestOperations restOperations) { ResponseEntity> response = - restOperations.exchange(NAME_URL_QUERY, GET, null, ref, name); + restOperations.exchange(NAME_URL_QUERY, GET, null, ref, name.getName()); throwExceptionOnError(response); @@ -201,14 +202,7 @@ public class CredHubTemplate implements CredHubOperations { } @Override - public List> getByNameWithHistory(final CredentialName name, Class credentialType) { - Assert.notNull(name, "credential name must not be null"); - - return getByNameWithHistory(name.getName(), credentialType); - } - - @Override - public List findByName(final String name) { + public List findByName(final CredentialName name) { Assert.notNull(name, "credential name must not be null"); return doWithRest(new RestOperationsCallback>() { @@ -217,7 +211,7 @@ public class CredHubTemplate implements CredHubOperations { RestOperations restOperations) { ResponseEntity response = restOperations .getForEntity(NAME_LIKE_URL_QUERY, - CredentialSummaryData.class, name); + CredentialSummaryData.class, name.getName()); throwExceptionOnError(response); @@ -226,13 +220,6 @@ public class CredHubTemplate implements CredHubOperations { }); } - @Override - public List findByName(final CredentialName name) { - Assert.notNull(name, "credential name must not be null"); - - return findByName(name.getName()); - } - @Override public List findByPath(final String path) { Assert.notNull(path, "credential path must not be null"); @@ -253,23 +240,67 @@ public class CredHubTemplate implements CredHubOperations { } @Override - public void deleteByName(final String name) { + public void deleteByName(final CredentialName name) { Assert.notNull(name, "credential name must not be null"); + final String name1 = name.getName(); + Assert.notNull(name1, "credential name must not be null"); + doWithRest(new RestOperationsCallback() { @Override public Void doWithRestOperations(RestOperations restOperations) { - restOperations.delete(NAME_URL_QUERY, name); + restOperations.delete(NAME_URL_QUERY, name1); return null; } }); } @Override - public void deleteByName(final CredentialName name) { + public List getPermissions(final CredentialName name) { Assert.notNull(name, "credential name must not be null"); - deleteByName(name.getName()); + return doWithRest(new RestOperationsCallback>() { + @Override + public List doWithRestOperations(RestOperations restOperations) { + ResponseEntity response = + restOperations.getForEntity(PERMISSIONS_URL_QUERY, + CredentialPermissions.class, name.getName()); + return response.getBody().getPermissions(); + } + }); + } + + @Override + public List addPermissions(final CredentialName name, CredentialPermission... permissions) { + Assert.notNull(name, "credential name must not be null"); + + final CredentialPermissions credentialPermissions = new CredentialPermissions(name, permissions); + + return doWithRest(new RestOperationsCallback>() { + @Override + public List doWithRestOperations(RestOperations restOperations) { + ResponseEntity response = + restOperations.exchange(PERMISSIONS_URL_PATH, POST, + new HttpEntity(credentialPermissions), + CredentialPermissions.class); + + return response.getBody().getPermissions(); + } + }); + } + + @Override + public void deletePermission(final CredentialName name, final Actor actor) { + Assert.notNull(name, "credential name must not be null"); + Assert.notNull(actor, "actor must not be null"); + + doWithRest(new RestOperationsCallback() { + @Override + public Void doWithRestOperations(RestOperations restOperations) { + restOperations.delete(PERMISSIONS_ACTOR_URL_QUERY, name.getName(), actor.getIdentity()); + return null; + } + }); } @Override diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/support/AdditionalPermission.java b/spring-credhub-core/src/main/java/org/springframework/credhub/support/AdditionalPermission.java deleted file mode 100644 index 31c7430..0000000 --- a/spring-credhub-core/src/main/java/org/springframework/credhub/support/AdditionalPermission.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * - * * Copyright 2013-2017 the original author or authors. - * * - * * 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 org.springframework.credhub.support; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Permissions applied to a credential in CredHub. If provided when a - * credential is written, these values will control what actors can access update - * or retrieve the credential. - * - * Objects of this type are constructed by the application and passed - * as part of a {@link CredentialRequest}. - * - * @author Scott Frederick - */ -public class AdditionalPermission { - private static final String APP_ACTOR_PREFIX = "mtls-app:"; - - private String actor; - private List operations; - - /** - * Create a set of permissions. Intended to be used internally for testing. - * Clients should use {@link #builder()} to construct instances of this class. - * - * @param actor the ID of the entity that will be allowed to access the credential - * @param operations the operations that the actor will be allowed to perform on the - * credential - */ - AdditionalPermission(String actor, List operations) { - this.actor = actor; - this.operations = operations; - } - - /** - * Get the ID of the entity that will be allowed to access the credential. - * - * @return the ID - */ - public String getActor() { - return this.actor; - } - - /** - * Get the set of operations that the actor will be allowed to perform on - * the credential. - * - * @return the operations - */ - public List getOperations() { - List operationValues = new ArrayList(operations.size()); - for (Operation operation : operations) { - operationValues.add(operation.operation()); - } - return operationValues; - } - - /** - * Create a builder that provides a fluent API for providing the values required - * to construct a {@link AdditionalPermission}. - * - * @return a builder - */ - public static AdditionalPermissionBuilder builder() { - return new AdditionalPermissionBuilder(); - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof AdditionalPermission)) - return false; - - AdditionalPermission that = (AdditionalPermission) o; - - if (actor != null ? !actor.equals(that.actor) : that.actor != null) - return false; - return operations != null ? operations.equals(that.operations) - : that.operations == null; - } - - @Override - public int hashCode() { - int result = actor != null ? actor.hashCode() : 0; - result = 31 * result + (operations != null ? operations.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "AdditionalPermission{" - + "actor='" + actor + '\'' - + ", operations=" + operations - + '}'; - } - - /** - * A builder that provides a fluent API for constructing {@link AdditionalPermission} - * instances. - */ - public static class AdditionalPermissionBuilder { - private String actor; - private ArrayList operations; - - AdditionalPermissionBuilder() { - } - - /** - * Set the ID of an application that will be allowed to access a credential. - * This will often be a Cloud Foundry application GUID. - * - * @param appId application ID - * @return the builder - */ - public AdditionalPermissionBuilder app(String appId) { - this.actor = APP_ACTOR_PREFIX + appId; - return this; - } - - /** - * Set the name of an actor that will be allowed to access the credential. - * - * @param actor actor name - * @return the builder - */ - public AdditionalPermissionBuilder actor(String actor) { - this.actor = actor; - return this; - } - - /** - * Set an {@link Operation} that the actor will be allowed to perform on - * the credential. Multiple operations can be provided with consecutive calls to - * this method. - * - * @param operation the {@link Operation} - * @return the builder - */ - public AdditionalPermissionBuilder operation(Operation operation) { - initOperations(); - this.operations.add(operation); - return this; - } - - /** - * Specify a set of {@link Operation}s that the actor will be allowed to perform - * on the credential. - * - * @param operations the {@link Operation}s - * @return the builder - */ - public AdditionalPermissionBuilder operations(Collection operations) { - initOperations(); - this.operations.addAll(operations); - return this; - } - - private void initOperations() { - if (this.operations == null) this.operations = new ArrayList(); - } - - /** - * Construct an {@link AdditionalPermission} with the provided values. - * - * @return an {@link AdditionalPermission} - */ - public AdditionalPermission build() { - List operations; - switch (this.operations == null ? 0 : this.operations.size()) { - case 0: - operations = java.util.Collections.emptyList(); - break; - case 1: - operations = java.util.Collections.singletonList(this.operations.get(0)); - break; - default: - operations = java.util.Collections.unmodifiableList(new ArrayList(this.operations)); - } - - return new AdditionalPermission(actor, operations); - } - } - - /** - * The set of operations that are allowed on a credential. - */ - public enum Operation { - READ("read"), - WRITE("write"); - - private final String operation; - - Operation(String operation) { - this.operation = operation; - } - - public String operation() { - return operation; - } - } -} diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialDetailsData.java b/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialDetailsData.java index fa6c459..8ed7b3c 100644 --- a/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialDetailsData.java +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialDetailsData.java @@ -1,18 +1,18 @@ /* * - * * Copyright 2013-2017 the original author or authors. - * * - * * 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. + * Copyright 2013-2017 the original author or authors. + * + * 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. * */ @@ -80,7 +80,7 @@ public class CredentialDetailsData { @Override public String toString() { - return "CredentialDetailResponse{" + return "CredentialDetailData{" + "data=" + data + '}'; } diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialPermissions.java b/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialPermissions.java new file mode 100644 index 0000000..ea550df --- /dev/null +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialPermissions.java @@ -0,0 +1,100 @@ +/* + * + * Copyright 2013-2017 the original author or authors. + * + * 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 org.springframework.credhub.support; + +import org.springframework.credhub.support.permissions.CredentialPermission; + +import java.util.Arrays; +import java.util.List; + +/** + * A collection of {@link CredentialPermission}s. Clients don't typically instantiate + * objects of this type, but will receive them in response to write and retrieve + * requests. + * + * @author Scott Frederick + */ +public class CredentialPermissions { + private CredentialName credentialName; + private List permissions; + + /** + * Create a {@link CredentialPermissions}. + */ + public CredentialPermissions() { + } + + /** + * Create a {@link CredentialPermissions} from the provided parameters. Intended for internal + * use. Clients will get {@link CredentialPermissions} objects populated from + * CredHub responses. + * + * @param credentialName the name of the credential that the permissions will apply to + * @param permissions a collection of {@link CredentialPermission}s + */ + public CredentialPermissions(CredentialName credentialName, CredentialPermission... permissions) { + this.credentialName = credentialName; + this.permissions = Arrays.asList(permissions); + } + + /** + * Get the name of the credential that the permissions apply to. + * + * @return the credential name + */ + public String getCredentialName() { + return this.credentialName.getName(); + } + + /** + * Get the collection of {@link CredentialPermission}s. + * + * @return the collection of {@link CredentialPermission}s + */ + public List getPermissions() { + return this.permissions; + } + + @Override + public String toString() { + return "CredentialPermissions{" + + "credentialName=" + credentialName + + ", permissions=" + permissions + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CredentialPermissions)) return false; + + CredentialPermissions that = (CredentialPermissions) o; + + if (credentialName != null ? !credentialName.equals(that.credentialName) : that.credentialName != null) + return false; + return permissions != null ? permissions.equals(that.permissions) : that.permissions == null; + } + + @Override + public int hashCode() { + int result = credentialName != null ? credentialName.hashCode() : 0; + result = 31 * result + (permissions != null ? permissions.hashCode() : 0); + return result; + } +} diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialRequest.java b/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialRequest.java index 102d289..7164575 100644 --- a/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialRequest.java +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialRequest.java @@ -1,18 +1,18 @@ /* * - * * Copyright 2013-2017 the original author or authors. - * * - * * 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. + * Copyright 2013-2017 the original author or authors. + * + * 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. * */ @@ -23,6 +23,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; +import org.springframework.credhub.support.permissions.CredentialPermission; import org.springframework.util.Assert; /** @@ -32,7 +33,7 @@ import org.springframework.util.Assert; */ public class CredentialRequest extends CredHubRequest { private T value; - private List additionalPermissions; + private List additionalPermissions; /** * Initialize a {@link CredentialRequest}. @@ -41,7 +42,7 @@ public class CredentialRequest extends CredHubRequest { */ protected CredentialRequest(CredentialType type) { this.credentialType = type; - additionalPermissions = new ArrayList(); + additionalPermissions = new ArrayList(); } /** @@ -58,11 +59,11 @@ public class CredentialRequest extends CredHubRequest { } /** - * Get the set of {@link AdditionalPermission} to assign to the credential. + * Get the set of {@link CredentialPermission} to assign to the credential. * - * @return the set of {@link AdditionalPermission} + * @return the set of {@link CredentialPermission} */ - public List getAdditionalPermissions() { + public List getAdditionalPermissions() { return this.additionalPermissions; } @@ -171,40 +172,40 @@ public class CredentialRequest extends CredHubRequest { } /** - * Add an {@link AdditionalPermission} to the permissions that will be assigned to the + * Add an {@link CredentialPermission} to the permissions that will be assigned to the * credential. * - * @param permission an {@link AdditionalPermission} to assign to the + * @param permission a {@link CredentialPermission} to assign to the * credential * @return the builder */ - public B additionalPermission(AdditionalPermission permission) { + public B permission(CredentialPermission permission) { targetObj.getAdditionalPermissions().add(permission); return thisObj; } /** - * Add a collection of {@link AdditionalPermission}s to the controls that will be + * Add a collection of {@link CredentialPermission}s to the controls that will be * assigned to the credential. * - * @param permissions an collection of {@link AdditionalPermission}s to + * @param permissions a collection of {@link CredentialPermission}s to * assign to the credential * @return the builder */ - public B additionalPermissions(Collection permissions) { + public B permissions(Collection permissions) { targetObj.getAdditionalPermissions().addAll(permissions); return thisObj; } /** - * Add a collection of {@link AdditionalPermission}s to the controls that will be + * Add a collection of {@link CredentialPermission}s to the controls that will be * assigned to the credential. * - * @param permissions an collection of {@link AdditionalPermission}s to + * @param permissions a collection of {@link CredentialPermission}s to * assign to the credential * @return the builder */ - public B additionalPermissions(AdditionalPermission... permissions) { + public B permissions(CredentialPermission... permissions) { targetObj.getAdditionalPermissions().addAll(Arrays.asList(permissions)); return thisObj; } diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialType.java b/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialType.java index a80ce19..8e4f615 100644 --- a/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialType.java +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/support/CredentialType.java @@ -1,24 +1,23 @@ /* * - * * Copyright 2013-2017 the original author or authors. - * * - * * 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. + * Copyright 2013-2017 the original author or authors. + * + * 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 org.springframework.credhub.support; -import com.fasterxml.jackson.annotation.JsonCreator; import org.springframework.credhub.support.certificate.CertificateCredential; import org.springframework.credhub.support.json.JsonCredential; import org.springframework.credhub.support.password.PasswordCredential; @@ -93,18 +92,9 @@ public enum CredentialType { } /** - * Convert a {@literal String} type to its enum value. - * - * @param type the {@literal String} type to convert - * @return the enum value + * {@inheritDoc} */ - @JsonCreator - public static CredentialType getTypeByString(String type) { - for (CredentialType value : CredentialType.values()) { - if (value.getValueType().equals(type)) { - return value; - } - } - return null; + public String toString() { + return valueType; } } diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/Actor.java b/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/Actor.java new file mode 100644 index 0000000..75856cc --- /dev/null +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/Actor.java @@ -0,0 +1,152 @@ +/* + * + * Copyright 2013-2017 the original author or authors. + * + * 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 org.springframework.credhub.support.permissions; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import org.springframework.util.Assert; + +import static org.springframework.credhub.support.permissions.ActorType.APP; +import static org.springframework.credhub.support.permissions.ActorType.OAUTH_CLIENT; +import static org.springframework.credhub.support.permissions.ActorType.USER; + +/** + * Identifies an entity that is authorized to perform operations on a CredHub credential. + * + * @author Scott Frederick + */ +public class Actor { + private ActorType authType; + private String primaryIdentifier; + + /** + * Create a new {@literal Actor}. + * + * @param actorType the type of the authorized entity + * @param primaryIdentifier the unique identifier of the authorized entity + */ + private Actor(ActorType actorType, String primaryIdentifier) { + this.authType = actorType; + this.primaryIdentifier = primaryIdentifier; + } + + /** + * Create an application identifier. An application is identified by a GUID generated + * by Cloud Foundry when the application is created. + * + * @param appId the Cloud Foundry application GUID + * @return the created {@literal Actor} + */ + public static Actor app(String appId) { + Assert.notNull(appId, "appId must not be null"); + return new Actor(APP, appId); + } + + /** + * Create a user identifier. A user is identified by a GUID generated by UAA when + * a user account is created and the ID of the identity zone the user was created in. + * + * @param zoneId the UAA identity zone ID + * @param userId the UAA user GUID + * @return the created {@literal Actor} + */ + public static Actor user(String zoneId, String userId) { + Assert.notNull(zoneId, "zoneId must not be null"); + Assert.notNull(userId, "userId must not be null"); + return new Actor(USER, zoneId + "/" + userId); + } + + /** + * Create an OAuth2 client identifier. A client identified by user-provided identifier + * and the ID of the identity zone the client was created in. + * + * @param zoneId the UAA identity zone ID + * @param clientId the UAA client ID + * @return the created {@literal Actor} + */ + public static Actor client(String zoneId, String clientId) { + Assert.notNull(zoneId, "zoneId must not be null"); + Assert.notNull(clientId, "clientId must not be null"); + return new Actor(OAUTH_CLIENT, zoneId + "/" + clientId); + } + + /** + * Get the type of the authorized entity. + * + * @return the entity type + */ + public ActorType getAuthType() { + return authType; + } + + /** + * Get the identity of the authorized entity. + * + * @return the identifier + */ + public String getPrimaryIdentifier() { + return primaryIdentifier; + } + + /** + * Get the full identifier for the authorized entity, which is a combination of the type and identity. + * + * @return the full identifier + */ + @JsonValue + public String getIdentity() { + return authType.getType() + ":" + primaryIdentifier; + } + + @JsonCreator + private static Actor createActor(String value) { + for (ActorType type : ActorType.values()) { + if (value.startsWith(type.getType())) { + return new Actor(type, value.substring(type.getType().length() + 1)); + } + } + return null; + } + + @Override + public String toString() { + return "Actor{" + + "authType=" + authType + + ", primaryIdentifier='" + primaryIdentifier + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Actor)) return false; + + Actor actor = (Actor) o; + + if (authType != actor.authType) return false; + return primaryIdentifier.equals(actor.primaryIdentifier); + } + + @Override + public int hashCode() { + int result = authType.hashCode(); + result = 31 * result + primaryIdentifier.hashCode(); + return result; + } +} diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/ActorType.java b/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/ActorType.java new file mode 100644 index 0000000..0347a66 --- /dev/null +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/ActorType.java @@ -0,0 +1,63 @@ +/* + * + * Copyright 2013-2017 the original author or authors. + * + * 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 org.springframework.credhub.support.permissions; + +/** + * The types of entities that can be authorized to perform operations on CredHub credentials. + * + * @author Scott Frederick + */ +public enum ActorType { + /** + * An Cloud Foundry application entity + */ + APP("mtls-app"), + + /** + * A UAA user entity, as can be used with a password grant + */ + USER("uaa-user"), + + /** + * A UAA client entity, as can be used with a client credentials grant + */ + OAUTH_CLIENT("uaa-client"); + + private final String type; + + ActorType(String type) { + this.type = type; + } + + /** + * Get the entity type. + * + * @return the entity type + */ + public String getType() { + return type; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return type; + } +} diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/CredentialPermission.java b/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/CredentialPermission.java new file mode 100644 index 0000000..36382d2 --- /dev/null +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/CredentialPermission.java @@ -0,0 +1,253 @@ +/* + * + * Copyright 2013-2017 the original author or authors. + * + * 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 org.springframework.credhub.support.permissions; + +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.springframework.credhub.support.CredentialRequest; +import org.springframework.util.Assert; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Permissions applied to a credential in CredHub. If provided when a + * credential is written, these values will control what actors can access update + * or retrieve the credential. + * + * Objects of this type are constructed by the application and passed + * as part of a {@link CredentialRequest}. + * + * @author Scott Frederick + */ +public class CredentialPermission { + private Actor actor; + + @JsonProperty + private List operations; + + /** + * Create a {@literal CredentialPermission}. + */ + private CredentialPermission() { + this.actor = null; + this.operations = null; + } + + /** + * Create a set of permissions. Intended to be used internally. + * Clients should use {@link #builder()} to construct instances of this class. + * + * @param actor the ID of the entity that will be allowed to access the credential + * @param operations the operations that the actor will be allowed to perform on the + * credential + */ + private CredentialPermission(Actor actor, List operations) { + this.actor = actor; + this.operations = operations; + } + + /** + * Get the ID of the entity that will be allowed to access the credential. + * + * @return the ID + */ + public Actor getActor() { + return this.actor; + } + + /** + * Get the set of operations that the actor will be allowed to perform on + * the credential. + * + * @return the operations + */ + public List getOperations() { + return operations; + } + + /** + * Get the set of operations that the actor will be allowed to perform on + * the credential. + * + * @return the operations + */ + @JsonGetter("operations") + private List getOperationsAsString() { + if (operations == null) { + return null; + } + + List operationValues = new ArrayList(operations.size()); + for (Operation operation : operations) { + operationValues.add(operation.operation()); + } + return operationValues; + } + + /** + * Create a builder that provides a fluent API for providing the values required + * to construct a {@link CredentialPermission}. + * + * @return a builder + */ + public static CredentialPermissionBuilder builder() { + return new CredentialPermissionBuilder(); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof CredentialPermission)) + return false; + + CredentialPermission that = (CredentialPermission) o; + + if (actor != null ? !actor.equals(that.actor) : that.actor != null) + return false; + return operations != null ? operations.equals(that.operations) + : that.operations == null; + } + + @Override + public int hashCode() { + int result = actor != null ? actor.hashCode() : 0; + result = 31 * result + (operations != null ? operations.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "CredentialPermission{" + + "actor='" + actor + '\'' + + ", operations=" + operations + + '}'; + } + + /** + * A builder that provides a fluent API for constructing {@link CredentialPermission} + * instances. + */ + public static class CredentialPermissionBuilder { + private Actor actor; + private ArrayList operations; + + CredentialPermissionBuilder() { + } + + /** + * Set the ID of an application that will be assigned permissions on a credential. + * This will often be a Cloud Foundry application GUID. + * + * @param appId application ID; must not be {@literal null} + * @return the builder + */ + public CredentialPermissionBuilder app(String appId) { + Assert.notNull(appId, "appId must not be null"); + Assert.isNull(actor, "only one actor can be specified"); + this.actor = Actor.app(appId); + return this; + } + + /** + * Set the ID of a user that will be assigned permissions on a credential. + * This is typically a GUID generated by UAA when a user account is created. + * + * @param zoneId zone ID; must not be {@literal null} + * @param userId user ID; must not be {@literal null} + * @return the builder + */ + public CredentialPermissionBuilder user(String zoneId, String userId) { + Assert.notNull(zoneId, "zoneId must not be null"); + Assert.notNull(userId, "userId must not be null"); + Assert.isNull(actor, "only one actor can be specified"); + this.actor = Actor.user(zoneId, userId); + return this; + } + + /** + * Set the ID of an OAuth2 client that will be assigned permissions on a credential. + * + * @param zoneId zone ID; must not be {@literal null} + * @param clientId OAuth2 client ID; must not be {@literal null} + * @return the builder + */ + public CredentialPermissionBuilder client(String zoneId, String clientId) { + Assert.notNull(zoneId, "zoneId must not be null"); + Assert.notNull(clientId, "clientId must not be null"); + Assert.isNull(actor, "only one actor can be specified"); + this.actor = Actor.client(zoneId, clientId); + return this; + } + + /** + * Set an {@link Operation} that the actor will be allowed to perform on + * the credential. Multiple operations can be provided with consecutive calls to + * this method. + * + * @param operation the {@link Operation} + * @return the builder + */ + public CredentialPermissionBuilder operation(Operation operation) { + initOperations(); + this.operations.add(operation); + return this; + } + + /** + * Specify a set of {@link Operation}s that the actor will be allowed to perform + * on the credential. + * + * @param operations the {@link Operation}s + * @return the builder + */ + public CredentialPermissionBuilder operations(Operation... operations) { + initOperations(); + this.operations.addAll(Arrays.asList(operations)); + return this; + } + + private void initOperations() { + if (this.operations == null) this.operations = new ArrayList(); + } + + /** + * Construct a {@link CredentialPermission} with the provided values. + * + * @return a {@link CredentialPermission} + */ + public CredentialPermission build() { + List operations; + switch (this.operations == null ? 0 : this.operations.size()) { + case 0: + operations = java.util.Collections.emptyList(); + break; + case 1: + operations = java.util.Collections.singletonList(this.operations.get(0)); + break; + default: + operations = java.util.Collections.unmodifiableList(new ArrayList(this.operations)); + } + + return new CredentialPermission(actor, operations); + } + } +} diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/Operation.java b/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/Operation.java new file mode 100644 index 0000000..ea62cb7 --- /dev/null +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/Operation.java @@ -0,0 +1,73 @@ +/* + * + * Copyright 2013-2017 the original author or authors. + * + * 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 org.springframework.credhub.support.permissions; + +/** + * The set of operations that are allowed on a credential. + * + * @author Scott Frederick + */ +public enum Operation { + /** + * Allows the value of a credential to be read. + */ + READ("read"), + + /** + * Allows the value of a credential to be updated. + */ + WRITE("write"), + + /** + * Allows a credential to be deleted. + */ + DELETE("delete"), + + /** + * Allows the permissions of a credential to be read. + */ + READ_ACL("read_acl"), + + /** + * Allows the permissions of a credential to be updated. + */ + WRITE_ACL("write_acl"); + + private final String operation; + + Operation(String operation) { + this.operation = operation; + } + + /** + * Get the value of the operation. + * + * @return the value of the operation. + */ + public String operation() { + return operation; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return operation; + } +} diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/package-info.java b/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/package-info.java new file mode 100644 index 0000000..c41a38a --- /dev/null +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/support/permissions/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2016-2017 the original author or authors. + * + * 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. + */ + +/** + * Java representations of CredHub JSON credential permissions. + */ +package org.springframework.credhub.support.permissions; \ No newline at end of file diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/support/JsonUtils.java b/spring-credhub-core/src/main/java/org/springframework/credhub/support/utils/JsonUtils.java similarity index 83% rename from spring-credhub-core/src/main/java/org/springframework/credhub/support/JsonUtils.java rename to spring-credhub-core/src/main/java/org/springframework/credhub/support/utils/JsonUtils.java index 6e7e139..fdab8ed 100644 --- a/spring-credhub-core/src/main/java/org/springframework/credhub/support/JsonUtils.java +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/support/utils/JsonUtils.java @@ -14,14 +14,16 @@ * limitations under the License. */ -package org.springframework.credhub.support; +package org.springframework.credhub.support.utils; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.util.ISO8601DateFormat; +import org.springframework.credhub.support.CredentialType; import java.util.ArrayList; import java.util.List; @@ -44,6 +46,8 @@ public class JsonUtils { objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy()); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true); + objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true); configureCredentialDetailTypeMapping(objectMapper); @@ -62,6 +66,10 @@ public class JsonUtils { subtypes.add(new NamedType(type.getModelClass(), type.getValueType())); } + registerSubtypes(objectMapper, subtypes); + } + + private static void registerSubtypes(ObjectMapper objectMapper, List subtypes) { objectMapper.registerSubtypes(subtypes.toArray(new NamedType[]{})); } } diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailCertificateUnitTests.java b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailCertificateUnitTests.java index 47df684..7e2e5bb 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailCertificateUnitTests.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailCertificateUnitTests.java @@ -95,26 +95,14 @@ public class CredHubTemplateDetailCertificateUnitTests } @Theory - public void getByNameWithString(@FromDataPoints("detail-responses") + public void getByName(@FromDataPoints("detail-responses") ResponseEntity> expectedResponse) { - verifyGetByNameUsingString(expectedResponse); + verifyGetByName(expectedResponse); } @Theory - public void getByNameWithCredentialName(@FromDataPoints("detail-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameUsingCredentialName(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingString(@FromDataPoints("data-responses") + public void getByNameWithHistory(@FromDataPoints("data-responses") ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingString(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingCredentialName(@FromDataPoints("data-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingCredentialName(expectedResponse); + verifyGetByNameWithHistory(expectedResponse); } } \ No newline at end of file diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailJsonUnitTests.java b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailJsonUnitTests.java index ecd0209..d9dc591 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailJsonUnitTests.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailJsonUnitTests.java @@ -78,26 +78,14 @@ public class CredHubTemplateDetailJsonUnitTests } @Theory - public void getByNameUsingString(@FromDataPoints("detail-responses") + public void getByName(@FromDataPoints("detail-responses") ResponseEntity> expectedResponse) { - verifyGetByNameUsingString(expectedResponse); + verifyGetByName(expectedResponse); } @Theory - public void getByNameUsingCredentialName(@FromDataPoints("detail-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameUsingCredentialName(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingString(@FromDataPoints("data-responses") + public void getByNameWithHistory(@FromDataPoints("data-responses") ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingString(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingCredentialName(@FromDataPoints("data-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingCredentialName(expectedResponse); + verifyGetByNameWithHistory(expectedResponse); } } \ No newline at end of file diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailPasswordUnitTests.java b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailPasswordUnitTests.java index 99505fc..08685bf 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailPasswordUnitTests.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailPasswordUnitTests.java @@ -91,26 +91,14 @@ public class CredHubTemplateDetailPasswordUnitTests } @Theory - public void getByNameUsingString(@FromDataPoints("detail-responses") + public void getByName(@FromDataPoints("detail-responses") ResponseEntity> expectedResponse) { - verifyGetByNameUsingString(expectedResponse); + verifyGetByName(expectedResponse); } @Theory - public void getByNameUsingCredentialName(@FromDataPoints("detail-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameUsingCredentialName(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingString(@FromDataPoints("data-responses") + public void getByNameWithHistory(@FromDataPoints("data-responses") ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingString(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingCredentialName(@FromDataPoints("data-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingCredentialName(expectedResponse); + verifyGetByNameWithHistory(expectedResponse); } } \ No newline at end of file diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailRsaUnitTests.java b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailRsaUnitTests.java index b81525c..c627ba0 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailRsaUnitTests.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailRsaUnitTests.java @@ -92,26 +92,14 @@ public class CredHubTemplateDetailRsaUnitTests } @Theory - public void getByNameUsingString(@FromDataPoints("detail-responses") + public void getByName(@FromDataPoints("detail-responses") ResponseEntity> expectedResponse) { - verifyGetByNameUsingString(expectedResponse); + verifyGetByName(expectedResponse); } @Theory - public void getByNameUsingCredentialName(@FromDataPoints("detail-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameUsingCredentialName(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingString(@FromDataPoints("data-responses") + public void getByNameWithHistory(@FromDataPoints("data-responses") ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingString(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingCredentialName(@FromDataPoints("data-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingCredentialName(expectedResponse); + verifyGetByNameWithHistory(expectedResponse); } } \ No newline at end of file diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailSshUnitTests.java b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailSshUnitTests.java index fd79589..9b9832a 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailSshUnitTests.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailSshUnitTests.java @@ -92,26 +92,14 @@ public class CredHubTemplateDetailSshUnitTests } @Theory - public void getByNameUsingString(@FromDataPoints("detail-responses") + public void getByName(@FromDataPoints("detail-responses") ResponseEntity> expectedResponse) { - verifyGetByNameUsingString(expectedResponse); + verifyGetByName(expectedResponse); } @Theory - public void getByNameUsingCredentialName(@FromDataPoints("detail-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameUsingCredentialName(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingString(@FromDataPoints("data-responses") + public void getByNameWithHistory(@FromDataPoints("data-responses") ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingString(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingCredentialName(@FromDataPoints("data-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingCredentialName(expectedResponse); + verifyGetByNameWithHistory(expectedResponse); } } \ No newline at end of file diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailUnitTestsBase.java b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailUnitTestsBase.java index 8df6137..a964d46 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailUnitTestsBase.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailUnitTestsBase.java @@ -150,31 +150,7 @@ public abstract class CredHubTemplateDetailUnitTestsBase extends CredHubTe } @SuppressWarnings("deprecation") - void verifyGetByNameUsingString(ResponseEntity> expectedResponse) { - when(restTemplate.exchange(eq(NAME_URL_QUERY_CURRENT), eq(GET), isNull(HttpEntity.class), - isA(ParameterizedTypeReference.class), eq(NAME.getName()))) - .thenReturn(expectedResponse); - - if (!expectedResponse.getStatusCode().equals(OK)) { - try { - credHubTemplate.getByName(NAME.getName(), String.class); - fail("Exception should have been thrown"); - } - catch (CredHubException e) { - assertThat(e.getMessage(), - containsString(expectedResponse.getStatusCode().toString())); - } - } - else { - CredentialDetails response = credHubTemplate - .getByName(NAME.getName(), getType()); - - assertResponseContainsExpectedCredentials(expectedResponse, response); - } - } - - @SuppressWarnings("deprecation") - void verifyGetByNameUsingCredentialName(ResponseEntity> expectedResponse) { + void verifyGetByName(ResponseEntity> expectedResponse) { when(restTemplate.exchange(eq(NAME_URL_QUERY_CURRENT), eq(GET), isNull(HttpEntity.class), isA(ParameterizedTypeReference.class), eq(NAME.getName()))) .thenReturn(expectedResponse); @@ -197,30 +173,7 @@ public abstract class CredHubTemplateDetailUnitTestsBase extends CredHubTe } @SuppressWarnings("deprecation") - void verifyGetByNameWithHistoryUsingString(ResponseEntity> expectedResponse) { - when(restTemplate.exchange(eq(NAME_URL_QUERY), eq(GET), isNull(HttpEntity.class), - isA(ParameterizedTypeReference.class), eq(NAME.getName()))) - .thenReturn(expectedResponse); - - if (!expectedResponse.getStatusCode().equals(OK)) { - try { - credHubTemplate.getByNameWithHistory(NAME.getName(), String.class); - fail("Exception should have been thrown"); - } - catch (CredHubException e) { - assertThat(e.getMessage(), - containsString(expectedResponse.getStatusCode().toString())); - } - } - else { - List> response = credHubTemplate.getByNameWithHistory(NAME.getName(), getType()); - - assertResponseContainsExpectedCredentials(expectedResponse, response); - } - } - - @SuppressWarnings("deprecation") - void verifyGetByNameWithHistoryUsingCredentialName(ResponseEntity> expectedResponse) { + void verifyGetByNameWithHistory(ResponseEntity> expectedResponse) { when(restTemplate.exchange(eq(NAME_URL_QUERY), eq(GET), isNull(HttpEntity.class), isA(ParameterizedTypeReference.class), eq(NAME.getName()))) .thenReturn(expectedResponse); diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailUserUnitTests.java b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailUserUnitTests.java index 22cb66f..00e16c0 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailUserUnitTests.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailUserUnitTests.java @@ -73,26 +73,14 @@ public class CredHubTemplateDetailUserUnitTests } @Theory - public void getByNameUsingString(@FromDataPoints("detail-responses") + public void getByName(@FromDataPoints("detail-responses") ResponseEntity> expectedResponse) { - verifyGetByNameUsingString(expectedResponse); + verifyGetByName(expectedResponse); } @Theory - public void getByNameUsingCredentialName(@FromDataPoints("detail-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameUsingCredentialName(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingString(@FromDataPoints("data-responses") + public void getByNameWithHistory(@FromDataPoints("data-responses") ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingString(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingCredentialName(@FromDataPoints("data-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingCredentialName(expectedResponse); + verifyGetByNameWithHistory(expectedResponse); } } \ No newline at end of file diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailValueUnitTests.java b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailValueUnitTests.java index fca2907..e8d4500 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailValueUnitTests.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateDetailValueUnitTests.java @@ -74,26 +74,14 @@ public class CredHubTemplateDetailValueUnitTests } @Theory - public void getByNameUsingString(@FromDataPoints("detail-responses") + public void getByName(@FromDataPoints("detail-responses") ResponseEntity> expectedResponse) { - verifyGetByNameUsingString(expectedResponse); + verifyGetByName(expectedResponse); } @Theory - public void getByNameUsingCredentialName(@FromDataPoints("detail-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameUsingCredentialName(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingString(@FromDataPoints("data-responses") + public void getByNameWithHistory(@FromDataPoints("data-responses") ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingString(expectedResponse); - } - - @Theory - public void getByNameWithHistoryUsingCredentialName(@FromDataPoints("data-responses") - ResponseEntity> expectedResponse) { - verifyGetByNameWithHistoryUsingCredentialName(expectedResponse); + verifyGetByNameWithHistory(expectedResponse); } } \ No newline at end of file diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateSummaryResponseUnitTests.java b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateSummaryResponseUnitTests.java index a7b9ef7..75137fe 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateSummaryResponseUnitTests.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateSummaryResponseUnitTests.java @@ -50,29 +50,7 @@ public class CredHubTemplateSummaryResponseUnitTests extends CredHubTemplateUnit new ResponseEntity(new CredentialSummaryData(), UNAUTHORIZED); @Theory - public void findByNameWithString(@FromDataPoints("responses") - ResponseEntity expectedResponse) { - when(restTemplate.getForEntity(NAME_LIKE_URL_QUERY, CredentialSummaryData.class, NAME.getName())) - .thenReturn(expectedResponse); - - if (!expectedResponse.getStatusCode().equals(OK)) { - try { - credHubTemplate.findByName(NAME.getName()); - fail("Exception should have been thrown"); - } - catch (CredHubException e) { - assertThat(e.getMessage(), containsString(expectedResponse.getStatusCode().toString())); - } - } - else { - List response = credHubTemplate.findByName(NAME.getName()); - - assertResponseContainsExpectedCredentials(expectedResponse, response); - } - } - - @Theory - public void findByNameWithCredentialName(@FromDataPoints("responses") + public void findByName(@FromDataPoints("responses") ResponseEntity expectedResponse) { when(restTemplate.getForEntity(NAME_LIKE_URL_QUERY, CredentialSummaryData.class, NAME.getName())) .thenReturn(expectedResponse); diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateUnitTests.java b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateUnitTests.java index a5edf17..cbb7461 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateUnitTests.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/core/CredHubTemplateUnitTests.java @@ -17,36 +17,108 @@ package org.springframework.credhub.core; import java.io.IOException; +import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; -import org.springframework.credhub.support.JsonUtils; +import org.springframework.credhub.support.permissions.Actor; +import org.springframework.credhub.support.permissions.ActorType; +import org.springframework.credhub.support.permissions.CredentialPermission; +import org.springframework.credhub.support.CredentialPermissions; +import org.springframework.credhub.support.utils.JsonUtils; +import org.springframework.credhub.support.permissions.Operation; import org.springframework.credhub.support.ServiceInstanceCredentialName; import org.springframework.credhub.support.ServicesData; import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.springframework.credhub.core.CredHubTemplate.INTERPOLATE_URL_PATH; import static org.springframework.credhub.core.CredHubTemplate.NAME_URL_QUERY; +import static org.springframework.credhub.core.CredHubTemplate.PERMISSIONS_ACTOR_URL_QUERY; +import static org.springframework.credhub.core.CredHubTemplate.PERMISSIONS_URL_PATH; +import static org.springframework.credhub.core.CredHubTemplate.PERMISSIONS_URL_QUERY; +import static org.springframework.http.HttpMethod.POST; import static org.springframework.http.HttpStatus.OK; @RunWith(MockitoJUnitRunner.class) public class CredHubTemplateUnitTests extends CredHubTemplateUnitTestsBase { @Test public void deleteByName() { - credHubTemplate.deleteByName(NAME.getName()); + credHubTemplate.deleteByName(NAME); verify(restTemplate).delete(NAME_URL_QUERY, NAME.getName()); } + @Test + public void getPermissions() { + CredentialPermissions expectedResponse = new CredentialPermissions( + NAME, + CredentialPermission.builder() + .app("app-id") + .operation(Operation.READ) + .operation(Operation.WRITE) + .build(), + CredentialPermission.builder() + .user("zone1", "user-id") + .operations(Operation.READ_ACL) + .operations(Operation.WRITE_ACL) + .operation(Operation.DELETE) + .build() + ); + + when(restTemplate.getForEntity(PERMISSIONS_URL_QUERY, CredentialPermissions.class, NAME.getName())) + .thenReturn(new ResponseEntity(expectedResponse, OK)); + + List response = credHubTemplate.getPermissions(NAME); + + assertNotNull(response); + assertThat(response.size(), equalTo(expectedResponse.getPermissions().size())); + assertThat(response, equalTo(expectedResponse.getPermissions())); + } + + @Test + public void addPermissions() { + CredentialPermission permission1 = CredentialPermission.builder() + .app("app-id") + .operation(Operation.READ) + .operation(Operation.WRITE) + .build(); + + CredentialPermission permission2 = CredentialPermission.builder() + .user("zone1", "user-id") + .operations(Operation.READ_ACL) + .operations(Operation.WRITE_ACL) + .operation(Operation.DELETE) + .build(); + + CredentialPermissions expectedResponse = new CredentialPermissions(NAME, permission1, permission2); + + when(restTemplate.exchange(PERMISSIONS_URL_PATH, POST, + new HttpEntity(expectedResponse), CredentialPermissions.class)) + .thenReturn(new ResponseEntity(expectedResponse, OK)); + + List response = credHubTemplate.addPermissions(NAME, permission1, permission2); + + assertNotNull(response); + assertThat(response.size(), equalTo(expectedResponse.getPermissions().size())); + assertThat(response, equalTo(expectedResponse.getPermissions())); + } + + @Test + public void deletePermission() { + credHubTemplate.deletePermission(NAME, Actor.app("appid1")); + + verify(restTemplate).delete(PERMISSIONS_ACTOR_URL_QUERY, NAME.getName(), ActorType.APP + ":appid1"); + } + @Test public void interpolateServiceData() throws IOException { ServiceInstanceCredentialName credentialName = ServiceInstanceCredentialName.builder() @@ -60,7 +132,7 @@ public class CredHubTemplateUnitTests extends CredHubTemplateUnitTestsBase { ServicesData expectedResponse = new ServicesData(); - when(restTemplate.exchange(INTERPOLATE_URL_PATH, HttpMethod.POST, + when(restTemplate.exchange(INTERPOLATE_URL_PATH, POST, new HttpEntity(vcapServices), ServicesData.class)) .thenReturn(new ResponseEntity(expectedResponse, OK)); diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/support/CredentialRequestUnitTestsBase.java b/spring-credhub-core/src/test/java/org/springframework/credhub/support/CredentialRequestUnitTestsBase.java index 2447574..71bd612 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/support/CredentialRequestUnitTestsBase.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/support/CredentialRequestUnitTestsBase.java @@ -22,12 +22,17 @@ import org.junit.Before; import org.junit.Test; import org.springframework.credhub.support.CredentialRequest.CredentialRequestBuilder; +import org.springframework.credhub.support.permissions.Actor; +import org.springframework.credhub.support.permissions.CredentialPermission; +import org.springframework.credhub.support.utils.JsonUtils; import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; -import static org.springframework.credhub.support.AdditionalPermission.Operation.READ; -import static org.springframework.credhub.support.AdditionalPermission.Operation.WRITE; +import static org.springframework.credhub.support.permissions.Operation.READ; +import static org.springframework.credhub.support.permissions.Operation.READ_ACL; +import static org.springframework.credhub.support.permissions.Operation.WRITE; +import static org.springframework.credhub.support.permissions.Operation.WRITE_ACL; import static org.valid4j.matchers.jsonpath.JsonPathMatchers.hasJsonPath; import static org.valid4j.matchers.jsonpath.JsonPathMatchers.hasNoJsonPath; import static org.valid4j.matchers.jsonpath.JsonPathMatchers.isJson; @@ -44,7 +49,7 @@ public abstract class CredentialRequestUnitTestsBase { @Test public void serializationWithOnePermission() throws Exception { requestBuilder - .additionalPermission(AdditionalPermission.builder() + .permission(CredentialPermission.builder() .app("app-id") .operation(READ) .build()); @@ -53,7 +58,7 @@ public abstract class CredentialRequestUnitTestsBase { assertThat(jsonValue, allOf(hasJsonPath("$.additional_permissions[0].actor", - equalTo("mtls-app:app-id")), + equalTo(Actor.app("app-id").getIdentity())), hasJsonPath("$.additional_permissions[0].operations[0]", equalTo("read")))); } @@ -61,29 +66,28 @@ public abstract class CredentialRequestUnitTestsBase { @Test public void serializationWithTwoPermissions() throws Exception { requestBuilder - .additionalPermission(AdditionalPermission.builder() - .app("app1-id") + .permission(CredentialPermission.builder() + .app("app-id") .operation(READ).operation(WRITE) .build()) - .additionalPermission(AdditionalPermission.builder() - .app("app2-id") - .operation(WRITE).operation(READ) + .permission(CredentialPermission.builder() + .user("zone1", "user-id") + .operations(READ_ACL, WRITE_ACL) .build()); String jsonValue = serializeToJson(requestBuilder); assertThat(jsonValue, allOf( hasJsonPath("$.additional_permissions[0].actor", - equalTo("mtls-app:app1-id")), + equalTo(Actor.app("app-id").getIdentity())), hasJsonPath("$.additional_permissions[0].operations[0]", equalTo("read")), - hasJsonPath("$.additional_permissions[0].operations[1]", - equalTo("write")), + hasJsonPath("$.additional_permissions[0].operations[1]", equalTo("write")), hasJsonPath("$.additional_permissions[1].actor", - equalTo("mtls-app:app2-id")), - hasJsonPath("$.additional_permissions[1].operations[0]", - equalTo("write")), - hasJsonPath("$.additional_permissions[1].operations[1]", - equalTo("read")))); + equalTo(Actor.user("zone1", "user-id").getIdentity())), + hasJsonPath("$.additional_permissions[1].operations[0]", equalTo("read_acl")), + hasJsonPath("$.additional_permissions[1].operations[1]", equalTo("write_acl")) + ) + ); } protected String serializeToJson(T requestBuilder) diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/support/JsonParsingUnitTestsBase.java b/spring-credhub-core/src/test/java/org/springframework/credhub/support/JsonParsingUnitTestsBase.java index 2cc74f4..1336cae 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/support/JsonParsingUnitTestsBase.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/support/JsonParsingUnitTestsBase.java @@ -21,6 +21,7 @@ import java.util.Date; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.util.ISO8601DateFormat; import org.junit.Before; +import org.springframework.credhub.support.utils.JsonUtils; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/support/ParametersRequestUnitTestsBase.java b/spring-credhub-core/src/test/java/org/springframework/credhub/support/ParametersRequestUnitTestsBase.java index 2a3c8ec..9bf72b4 100644 --- a/spring-credhub-core/src/test/java/org/springframework/credhub/support/ParametersRequestUnitTestsBase.java +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/support/ParametersRequestUnitTestsBase.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Before; import org.springframework.credhub.support.ParametersRequest.ParametersRequestBuilder; +import org.springframework.credhub.support.utils.JsonUtils; import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.equalTo; diff --git a/spring-credhub-core/src/test/java/org/springframework/credhub/support/permissions/CredentialPermissionsUnitTests.java b/spring-credhub-core/src/test/java/org/springframework/credhub/support/permissions/CredentialPermissionsUnitTests.java new file mode 100644 index 0000000..67ac4b8 --- /dev/null +++ b/spring-credhub-core/src/test/java/org/springframework/credhub/support/permissions/CredentialPermissionsUnitTests.java @@ -0,0 +1,126 @@ +/* + * + * Copyright 2013-2017 the original author or authors. + * + * 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 org.springframework.credhub.support.permissions; + +import java.util.List; + +import com.fasterxml.jackson.core.JsonProcessingException; +import org.junit.Test; + +import org.springframework.credhub.support.CredentialPermissions; +import org.springframework.credhub.support.JsonParsingUnitTestsBase; +import org.springframework.credhub.support.SimpleCredentialName; +import org.springframework.credhub.support.utils.JsonUtils; + +import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; +import static org.springframework.credhub.support.permissions.ActorType.APP; +import static org.springframework.credhub.support.permissions.ActorType.USER; +import static org.springframework.credhub.support.permissions.Operation.DELETE; +import static org.springframework.credhub.support.permissions.Operation.READ; +import static org.springframework.credhub.support.permissions.Operation.READ_ACL; +import static org.springframework.credhub.support.permissions.Operation.WRITE; +import static org.springframework.credhub.support.permissions.Operation.WRITE_ACL; +import static org.valid4j.matchers.jsonpath.JsonPathMatchers.hasJsonPath; +import static org.valid4j.matchers.jsonpath.JsonPathMatchers.isJson; + +public class CredentialPermissionsUnitTests extends JsonParsingUnitTestsBase { + @Test + public void deserializePermissions() throws Exception { + String json = "{\"credential_name\": \"/c/example\"," + + "\"permissions\": [" + + " {" + + " \"actor\": \"mtls-app:appid1\"," + + " \"operations\": [" + + " \"read\"," + + " \"write\"," + + " \"delete\"," + + " \"read_acl\"," + + " \"write_acl\"" + + " ]" + + " }," + + " {" + + " \"actor\": \"uaa-user:zone1/userid\"," + + " \"operations\": [" + + " \"read\"" + + " ]" + + " }" + + " ]}"; + + CredentialPermissions permissions = parsePermissions(json); + + assertThat(permissions.getCredentialName(), equalTo("/c/example")); + assertThat(permissions.getPermissions().size(), equalTo(2)); + + CredentialPermission permission = permissions.getPermissions().get(0); + assertThat(permission.getActor().getAuthType(), equalTo(APP)); + assertThat(permission.getActor().getPrimaryIdentifier(), equalTo("appid1")); + + List operations = permission.getOperations(); + assertThat(operations.size(), equalTo(5)); + assertThat(operations, contains(READ, WRITE, DELETE, READ_ACL, WRITE_ACL)); + + permission = permissions.getPermissions().get(1); + assertThat(permission.getActor().getAuthType(), equalTo(USER)); + assertThat(permission.getActor().getPrimaryIdentifier(), equalTo("zone1/userid")); + + operations = permission.getOperations(); + assertThat(operations.size(), equalTo(1)); + assertThat(operations, contains(READ)); + } + + @Test + public void deserializeWithNoPermissions() throws Exception { + String json = "{\"permissions\": []}"; + + CredentialPermissions permissions = parsePermissions(json); + + assertThat(permissions.getPermissions().size(), equalTo(0)); + } + + @Test + public void serialize() throws Exception { + CredentialPermissions permissions = new CredentialPermissions(new SimpleCredentialName("example", "credentialName"), + CredentialPermission.builder() + .app("appid1") + .operations(READ, WRITE) + .build()); + + String jsonValue = serializeToJson(permissions); + + assertThat(jsonValue, + allOf(hasJsonPath("$.credential_name", equalTo("/example/credentialName")), + hasJsonPath("$.permissions[0].actor", equalTo(Actor.app("appid1").getIdentity())), + hasJsonPath("$.permissions[0].operations[0]", equalTo("read")), + hasJsonPath("$.permissions[0].operations[1]", equalTo("write")))); + } + + protected String serializeToJson(Object obj) throws JsonProcessingException { + String jsonValue = JsonUtils.buildObjectMapper().writeValueAsString(obj); + assertThat(jsonValue, isJson()); + return jsonValue; + } + + @SuppressWarnings("unchecked") + private CredentialPermissions parsePermissions(String json) throws java.io.IOException { + return objectMapper.readValue(json, CredentialPermissions.class); + } +} diff --git a/spring-credhub-demo/build.gradle b/spring-credhub-demo/build.gradle index 0b510fc..502c3c1 100644 --- a/spring-credhub-demo/build.gradle +++ b/spring-credhub-demo/build.gradle @@ -51,6 +51,7 @@ dependencies { } repositories { + mavenLocal() mavenCentral() maven { url "https://repo.spring.io/libs-snapshot-local" } maven { url "https://repo.spring.io/libs-milestone-local" } diff --git a/spring-credhub-demo/src/main/java/org/springframework/credhub/demo/CredHubDemoController.java b/spring-credhub-demo/src/main/java/org/springframework/credhub/demo/CredHubDemoController.java index 00fa838..223db6a 100644 --- a/spring-credhub-demo/src/main/java/org/springframework/credhub/demo/CredHubDemoController.java +++ b/spring-credhub-demo/src/main/java/org/springframework/credhub/demo/CredHubDemoController.java @@ -24,9 +24,9 @@ import java.util.Map; import java.util.UUID; import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.beans.factory.annotation.Value; import org.springframework.credhub.core.CredHubTemplate; -import org.springframework.credhub.support.AdditionalPermission; +import org.springframework.credhub.support.permissions.Actor; +import org.springframework.credhub.support.permissions.CredentialPermission; import org.springframework.credhub.support.CredentialDetails; import org.springframework.credhub.support.CredentialName; import org.springframework.credhub.support.CredentialSummary; @@ -38,12 +38,16 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; -import static org.springframework.credhub.support.AdditionalPermission.Operation.READ; +import static org.springframework.credhub.support.permissions.Operation.DELETE; +import static org.springframework.credhub.support.permissions.Operation.READ; +import static org.springframework.credhub.support.permissions.Operation.READ_ACL; +import static org.springframework.credhub.support.permissions.Operation.WRITE; +import static org.springframework.credhub.support.permissions.Operation.WRITE_ACL; @RestController public class CredHubDemoController { - @Value("${vcap.application.application_id:}") - private String appId; + private static final String APP_GUID_1 = UUID.randomUUID().toString(); + private static final String APP_GUID_2 = UUID.randomUUID().toString(); private CredHubTemplate credHubTemplate; @@ -67,6 +71,14 @@ public class CredHubDemoController { findCredentialsByPath(credentialName.getName(), results); + getCredentialPermissions(credentialName, results); + + addCredentialPermissions(credentialName, results); + + deleteCredentialPermission(credentialName, results); + + getCredentialPermissions(credentialName, results); + interpolateServiceData(credentialName, results); deleteCredentials(credentialName, results); @@ -83,9 +95,10 @@ public class CredHubDemoController { .overwrite(true) .name(new SimpleCredentialName("spring-credhub", "demo", "credentials_json")) .value(value) - .additionalPermission(AdditionalPermission.builder() - .app(UUID.randomUUID().toString()) + .permission(CredentialPermission.builder() + .app(APP_GUID_1) .operation(READ) + .operation(WRITE) .build()) .build(); @@ -138,6 +151,37 @@ public class CredHubDemoController { } } + private void getCredentialPermissions(CredentialName name, Results results) { + try { + List retrievedDetails = credHubTemplate.getPermissions(name); + saveResults(results, "Successfully retrieved credential permissions: ", retrievedDetails); + } catch (Exception e) { + saveResults(results, "Error retrieving credential permissions: ", e.getMessage()); + } + } + + private void addCredentialPermissions(CredentialName name, Results results) { + try { + CredentialPermission permission = CredentialPermission.builder() + .app(APP_GUID_2) + .operations(READ_ACL, WRITE_ACL, DELETE) + .build(); + + List permissions = credHubTemplate.addPermissions(name, permission); + saveResults(results, "Successfully added permissions: ", permissions); + } catch (Exception e) { + saveResults(results, "Error adding permission: ", e.getMessage()); + } } + + private void deleteCredentialPermission(CredentialName name, Results results) { + try { + credHubTemplate.deletePermission(name, Actor.app(APP_GUID_1)); + saveResults(results, "Successfully deleted permission"); + } catch (Exception e) { + saveResults(results, "Error deleting permission: ", e.getMessage()); + } + } + private void interpolateServiceData(CredentialName name, Results results) { try { ServicesData request = buildServicesData(name.getName());