Separate credentials, permissions, and interpolation operations into separate interfaces.

This commit is contained in:
Scott Frederick
2018-10-17 13:18:43 -05:00
parent d3dcfee247
commit c75b9d8eb2
17 changed files with 966 additions and 593 deletions

View File

@@ -22,6 +22,7 @@ import java.util.logging.Logger;
import org.springframework.cloud.cloudfoundry.CloudFoundryRawServiceData;
import org.springframework.cloud.cloudfoundry.ServiceDataPostProcessor;
import org.springframework.credhub.configuration.CredHubTemplateFactory;
import org.springframework.credhub.core.CredHubInterpolationOperations;
import org.springframework.credhub.core.CredHubOperations;
import org.springframework.credhub.core.CredHubProperties;
import org.springframework.credhub.support.ServicesData;
@@ -38,7 +39,7 @@ public class CredHubInterpolationServiceDataPostProcessor
private Logger logger = Logger
.getLogger(CredHubInterpolationServiceDataPostProcessor.class.getName());
private CredHubOperations credHubOperations;
private CredHubInterpolationOperations credHubOperations;
/**
* Initialize the service data post-processor.
@@ -54,7 +55,8 @@ public class CredHubInterpolationServiceDataPostProcessor
&& !credHubProperties.getUrl().isEmpty()) {
credHubOperations = credHubTemplateFactroy.credHubTemplate(
credHubProperties,
credHubTemplateFactroy.clientHttpRequestFactoryWrapper());
credHubTemplateFactroy.clientHttpRequestFactoryWrapper())
.interpolation();
}
else {
logger.log(Level.WARNING,
@@ -73,14 +75,14 @@ public class CredHubInterpolationServiceDataPostProcessor
*
* @param credHubOperations the CredHubOperations to use
*/
CredHubInterpolationServiceDataPostProcessor(CredHubOperations credHubOperations) {
CredHubInterpolationServiceDataPostProcessor(CredHubInterpolationOperations credHubOperations) {
this.credHubOperations = credHubOperations;
}
/**
* Process the provided {@literal serviceData} parsed from {@literal VCAP_SERVICES} by
* Spring Cloud Connectors using the
* {@link CredHubOperations#interpolateServiceData(ServicesData)} API.
* {@link org.springframework.credhub.core.CredHubInterpolationOperations#interpolateServiceData(ServicesData)} API.
*
* @param serviceData raw service data parsed from {@literal VCAP_SERVICES}
* @return serviceData with CredHub references replaced by stored credentials

View File

@@ -32,7 +32,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.cloud.cloudfoundry.CloudFoundryRawServiceData;
import org.springframework.credhub.core.CredHubException;
import org.springframework.credhub.core.CredHubOperations;
import org.springframework.credhub.core.CredHubInterpolationOperations;
import org.springframework.credhub.support.ServicesData;
import org.springframework.http.HttpStatus;
@@ -45,7 +45,7 @@ import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class CredHubInterpolationServiceDataPostProcessorTests {
@Mock
private CredHubOperations credHubOperations;
private CredHubInterpolationOperations credHubOperations;
@Test
public void processServiceData() {

View File

@@ -0,0 +1,135 @@
/*
* 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.
*/
package org.springframework.credhub.core;
import org.springframework.credhub.support.CredentialDetails;
import org.springframework.credhub.support.CredentialName;
import org.springframework.credhub.support.CredentialRequest;
import org.springframework.credhub.support.CredentialSummary;
import org.springframework.credhub.support.ParametersRequest;
import java.util.List;
/**
* Specifies the interactions with CredHub to save, generate, retrieve,
* and delete credentials.
*
* @author Scott Frederick
*/
public interface CredHubCredentialsOperations {
/**
* Write a new credential to CredHub, or overwrite an existing credential with a new
* value.
*
* @param credentialRequest the credential to write to CredHub; must not be {@literal null}
* @param <T> the credential implementation type
* @return the details of the written credential
*/
<T> CredentialDetails<T> write(final CredentialRequest<T> credentialRequest);
/**
* Generate a new credential in CredHub, or overwrite an existing credential with a new
* generated value.
*
* @param parametersRequest the parameters of the new credential to generate in CredHub;
* must not be {@literal null}
* @param <T> the credential implementation type
* @param <P> the credential parameter implementation type
* @return the details of the generated credential
*/
<T, P> CredentialDetails<T> generate(final ParametersRequest<P> parametersRequest);
/**
* Regenerate a credential in CredHub. Only credentials that were previously generated can be
* re-generated.
*
* @param name the name of the credential; must not be {@literal null}
* @param <T> the credential implementation type
* @return the details of the regenerated credential
*/
<T> CredentialDetails<T> regenerate(final CredentialName name);
/**
* Retrieve a credential using its ID, as returned in a write request.
*
* @param id the ID of the credential; must not be {@literal null}
* @param credentialType the type of the credential to be retrieved; must not be {@literal null}
* @param <T> the credential implementation type
* @return the details of the retrieved credential
*/
<T> CredentialDetails<T> getById(final String id, final Class<T> 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 <T> the credential implementation type
* @return the details of the retrieved credential
*/
<T> CredentialDetails<T> getByName(final CredentialName name, final Class<T> 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 <T> the credential implementation type
* @return the details of the retrieved credential, including history
*/
<T> List<CredentialDetails<T>> getByNameWithHistory(final CredentialName name, final Class<T> credentialType);
/**
* Retrieve a credential using its name, as passed to a write request.
* A collection of stored values for the named credential will be returned,
* with the specified number of historical values.
*
* @param name the name of the credential; must not be {@literal null}
* @param versions the number of historical versions to retrieve
* @param credentialType the type of credential expected to be returned
* @param <T> the credential implementation type
* @return the details of the retrieved credential, including history
*/
<T> List<CredentialDetails<T>> getByNameWithHistory(final CredentialName name, int versions,
final Class<T> 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<CredentialSummary> findByName(final CredentialName name);
/**
* Find a credential using a path.
*
* @param path the path to the credential; must not be {@literal null}
* @return a summary of the credential search results
*/
List<CredentialSummary> findByPath(final String path);
/**
* Delete a credential by its full name.
*
* @param name the name of the credential; must not be {@literal null}
*/
void deleteByName(final CredentialName name);
}

View File

@@ -0,0 +1,286 @@
/*
* 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.
*/
package org.springframework.credhub.core;
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.CredentialRequest;
import org.springframework.credhub.support.CredentialSummary;
import org.springframework.credhub.support.CredentialSummaryData;
import org.springframework.credhub.support.ParametersRequest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.HttpMethod.PUT;
/**
* Implements the interactions with CredHub to save, retrieve,
* and delete credentials.
*
* @author Scott Frederick
*/
public class CredHubCredentialsTemplate implements CredHubCredentialsOperations {
static final String BASE_URL_PATH = "/api/v1/data";
static final String ID_URL_PATH = BASE_URL_PATH + "/{id}";
static final String NAME_URL_QUERY = BASE_URL_PATH + "?name={name}";
static final String NAME_URL_QUERY_CURRENT = NAME_URL_QUERY + "&current=true";
static final String NAME_URL_QUERY_VERSIONS = NAME_URL_QUERY + "&versions={versions}";
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 REGENERATE_URL_PATH = "/api/v1/regenerate";
private CredHubOperations credHubOperations;
/**
* Create a new {@link CredHubCredentialsTemplate}.
*
* @param credHubOperations the {@link CredHubOperations} to use for interactions with CredHub
*/
CredHubCredentialsTemplate(CredHubOperations credHubOperations) {
this.credHubOperations = credHubOperations;
}
@Override
public <T> CredentialDetails<T> write(final CredentialRequest<T> credentialRequest) {
Assert.notNull(credentialRequest, "credentialRequest must not be null");
final ParameterizedTypeReference<CredentialDetails<T>> ref =
new ParameterizedTypeReference<CredentialDetails<T>>() {};
return credHubOperations.doWithRest(new RestOperationsCallback<CredentialDetails<T>>() {
@Override
public CredentialDetails<T> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDetails<T>> response =
restOperations.exchange(BASE_URL_PATH, PUT,
new HttpEntity<>(credentialRequest), ref);
throwExceptionOnError(response);
return response.getBody();
}
});
}
@Override
public <T, P> CredentialDetails<T> generate(final ParametersRequest<P> parametersRequest) {
Assert.notNull(parametersRequest, "parametersRequest must not be null");
final ParameterizedTypeReference<CredentialDetails<T>> ref =
new ParameterizedTypeReference<CredentialDetails<T>>() {};
return credHubOperations.doWithRest(new RestOperationsCallback<CredentialDetails<T>>() {
@Override
public CredentialDetails<T> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDetails<T>> response =
restOperations.exchange(BASE_URL_PATH, POST,
new HttpEntity<>(parametersRequest), ref);
throwExceptionOnError(response);
return response.getBody();
}
});
}
@Override
public <T> CredentialDetails<T> regenerate(final CredentialName name) {
Assert.notNull(name, "credential name must not be null");
final ParameterizedTypeReference<CredentialDetails<T>> ref =
new ParameterizedTypeReference<CredentialDetails<T>>() {};
return credHubOperations.doWithRest(new RestOperationsCallback<CredentialDetails<T>>() {
@Override
public CredentialDetails<T> doWithRestOperations(RestOperations restOperations) {
Map<String, Object> request = new HashMap<>(1);
request.put("name", name.getName());
ResponseEntity<CredentialDetails<T>> response =
restOperations.exchange(REGENERATE_URL_PATH, POST,
new HttpEntity<>(request), ref);
throwExceptionOnError(response);
return response.getBody();
}
});
}
@Override
public <T> CredentialDetails<T> getById(final String id, final Class<T> credentialType) {
Assert.notNull(id, "credential id must not be null");
Assert.notNull(credentialType, "credential type must not be null");
final ParameterizedTypeReference<CredentialDetails<T>> ref =
new ParameterizedTypeReference<CredentialDetails<T>>() {};
return credHubOperations.doWithRest(new RestOperationsCallback<CredentialDetails<T>>() {
@Override
public CredentialDetails<T> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDetails<T>> response =
restOperations.exchange(ID_URL_PATH, GET, null, ref, id);
throwExceptionOnError(response);
return response.getBody();
}
});
}
@Override
public <T> CredentialDetails<T> getByName(final CredentialName name, final Class<T> credentialType) {
Assert.notNull(name, "credential name must not be null");
Assert.notNull(credentialType, "credential type must not be null");
final ParameterizedTypeReference<CredentialDetailsData<T>> ref =
new ParameterizedTypeReference<CredentialDetailsData<T>>() {};
return credHubOperations.doWithRest(new RestOperationsCallback<CredentialDetails<T>>() {
@Override
public CredentialDetails<T> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDetailsData<T>> response =
restOperations.exchange(NAME_URL_QUERY_CURRENT, GET, null, ref, name.getName());
throwExceptionOnError(response);
return response.getBody().getData().get(0);
}
});
}
@Override
public <T> List<CredentialDetails<T>> getByNameWithHistory(final CredentialName name, final Class<T> credentialType) {
Assert.notNull(name, "credential name must not be null");
Assert.notNull(credentialType, "credential type must not be null");
final ParameterizedTypeReference<CredentialDetailsData<T>> ref =
new ParameterizedTypeReference<CredentialDetailsData<T>>() {};
return credHubOperations.doWithRest(new RestOperationsCallback<List<CredentialDetails<T>>>() {
@Override
public List<CredentialDetails<T>> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDetailsData<T>> response =
restOperations.exchange(NAME_URL_QUERY, GET, null, ref, name.getName());
throwExceptionOnError(response);
return response.getBody().getData();
}
});
}
@Override
public <T> List<CredentialDetails<T>> getByNameWithHistory(final CredentialName name, final int versions,
final Class<T> credentialType) {
Assert.notNull(name, "credential name must not be null");
Assert.notNull(credentialType, "credential type must not be null");
final ParameterizedTypeReference<CredentialDetailsData<T>> ref =
new ParameterizedTypeReference<CredentialDetailsData<T>>() {};
return credHubOperations.doWithRest(new RestOperationsCallback<List<CredentialDetails<T>>>() {
@Override
public List<CredentialDetails<T>> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDetailsData<T>> response =
restOperations.exchange(NAME_URL_QUERY_VERSIONS, GET, null, ref,
name.getName(), versions);
throwExceptionOnError(response);
return response.getBody().getData();
}
});
}
@Override
public List<CredentialSummary> findByName(final CredentialName name) {
Assert.notNull(name, "credential name must not be null");
return credHubOperations.doWithRest(new RestOperationsCallback<List<CredentialSummary>>() {
@Override
public List<CredentialSummary> doWithRestOperations(
RestOperations restOperations) {
ResponseEntity<CredentialSummaryData> response = restOperations
.getForEntity(NAME_LIKE_URL_QUERY,
CredentialSummaryData.class, name.getName());
throwExceptionOnError(response);
return response.getBody().getCredentials();
}
});
}
@Override
public List<CredentialSummary> findByPath(final String path) {
Assert.notNull(path, "credential path must not be null");
return credHubOperations.doWithRest(new RestOperationsCallback<List<CredentialSummary>>() {
@Override
public List<CredentialSummary> doWithRestOperations(
RestOperations restOperations) {
ResponseEntity<CredentialSummaryData> response = restOperations
.getForEntity(PATH_URL_QUERY, CredentialSummaryData.class,
path);
throwExceptionOnError(response);
return response.getBody().getCredentials();
}
});
}
@Override
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");
credHubOperations.doWithRest(new RestOperationsCallback<Void>() {
@Override
public Void doWithRestOperations(RestOperations restOperations) {
restOperations.delete(NAME_URL_QUERY, name1);
return null;
}
});
}
/**
* Helper method to throw an appropriate exception if a request to CredHub
* returns with an error code.
*
* @param response a {@link ResponseEntity} returned from {@link RestTemplate}
*/
private void throwExceptionOnError(ResponseEntity<?> response) {
if (!response.getStatusCode().equals(HttpStatus.OK)) {
throw new CredHubException(response.getStatusCode());
}
}
}

View File

@@ -0,0 +1,88 @@
/*
* 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.
*/
package org.springframework.credhub.core;
import org.springframework.credhub.support.ServicesData;
/**
* Specifies the interactions with CredHub to interpolate service binding credentials.
*
* @author Scott Frederick
*/
public interface CredHubInterpolationOperations {
/**
* Search the provided data structure of bound service credentials, looking for
* references to CredHub credentials. Any CredHub credentials found in the data
* structure will be replaced by the credential value stored in CredHub.
*
* Example:
*
* A JSON data structure parsed from a {@literal VCAP_SERVICES} environment
* variable might look like this if the service broker that provided the binding
* is integrated with CredHub:
*
* <pre>
* {@code
* {
* "service-offering": [{
* "credentials": {
* "credhub-ref": "((/c/service-broker/service-offering/1111-2222-3333-4444/credentials))"
* }
* "label": "service-offering",
* "name": "service-instance",
* "plan": "standard",
* "tags": ["
* "cloud-service"
* ]
* }]
* }
* }
* </pre>
*
* Assuming that CredHub has a credential with the name
* {@literal /c/service-broker/service-offering/1111-2222-3333-4444/credentials},
* passing the data structure above to this method would result in the
* {@literal credhub-ref} field being replaced by the credentials stored in CredHub:
*
* <pre>
* {@code
* {
* "service-offering": [{
* "credentials": {
* "url": "https://servicehost.example.com/",
* "username": "someuser",
* "password": "secret"
* }
* "label": "service-offering",
* "name": "service-instance",
* "plan": "standard",
* "tags": ["
* "cloud-service"
* ]
* }]
* }
* }
* </pre>
*
* @param serviceData a data structure of bound service credentials, as would be
* parsed from the {@literal VCAP_SERVICES} environment variable provided to
* applications running on Cloud Foundry
* @return the serviceData structure with CredHub references replaced by stored
* credential values
*/
ServicesData interpolateServiceData(final ServicesData serviceData);
}

View File

@@ -0,0 +1,76 @@
/*
* 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.
*/
package org.springframework.credhub.core;
import org.springframework.credhub.support.ServicesData;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
import static org.springframework.http.HttpMethod.POST;
/**
* Implements the main interaction with CredHub to interpolate service binding credentials.
*
* @author Scott Frederick
*/
public class CredHubInterpolationTemplate implements CredHubInterpolationOperations {
static final String INTERPOLATE_URL_PATH = "/api/v1/interpolate";
private CredHubOperations credHubOperations;
/**
* Create a new {@link CredHubInterpolationTemplate}.
*
* @param credHubOperations the {@link CredHubOperations} to use for interactions with CredHub
*/
CredHubInterpolationTemplate(CredHubOperations credHubOperations) {
this.credHubOperations = credHubOperations;
}
@Override
public ServicesData interpolateServiceData(final ServicesData serviceData) {
Assert.notNull(serviceData, "serviceData must not be null");
return credHubOperations.doWithRest(new RestOperationsCallback<ServicesData>() {
@Override
public ServicesData doWithRestOperations(RestOperations restOperations) {
ResponseEntity<ServicesData> response = restOperations
.exchange(INTERPOLATE_URL_PATH, POST,
new HttpEntity<>(serviceData), ServicesData.class);
throwExceptionOnError(response);
return response.getBody();
}
});
}
/**
* Helper method to throw an appropriate exception if a request to CredHub
* returns with an error code.
*
* @param response a {@link ResponseEntity} returned from {@link RestTemplate}
*/
private void throwExceptionOnError(ResponseEntity<?> response) {
if (!response.getStatusCode().equals(HttpStatus.OK)) {
throw new CredHubException(response.getStatusCode());
}
}
}

View File

@@ -16,213 +16,34 @@
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;
import org.springframework.credhub.support.ParametersRequest;
import org.springframework.credhub.support.ServicesData;
import org.springframework.credhub.support.CredentialRequest;
import org.springframework.web.client.RestTemplate;
/**
* Specifies the main interaction with CredHub to save, generate, retrieve,
* and delete credentials.
* Specifies the main interaction with CredHub.
*
* @author Scott Frederick
*/
public interface CredHubOperations {
/**
* Write a new credential to CredHub, or overwrite an existing credential with a new
* value.
* Get the operations for saving, retrieving, and deleting credentials.
*
* @param credentialRequest the credential to write to CredHub; must not be {@literal null}
* @param <T> the credential implementation type
* @return the details of the written credential
* @return the credentials operations
*/
<T> CredentialDetails<T> write(final CredentialRequest<T> credentialRequest);
CredHubCredentialsOperations credentials();
/**
* Generate a new credential in CredHub, or overwrite an existing credential with a new
* generated value.
* Get the operations for adding, retrieving, and deleting credential permissions.
*
* @param parametersRequest the parameters of the new credential to generate in CredHub;
* must not be {@literal null}
* @param <T> the credential implementation type
* @param <P> the credential parameter implementation type
* @return the details of the generated credential
* @return the permissions operations
*/
<T, P> CredentialDetails<T> generate(final ParametersRequest<P> parametersRequest);
CredHubPermissionsOperations permissions();
/**
* Regenerate a credential in CredHub. Only credentials that were previously generated can be
* re-generated.
* Get the operations interpolating service binding credentials.
*
* @param name the name of the credential; must not be {@literal null}
* @param <T> the credential implementation type
* @return the details of the regenerated credential
* @return the interpolation operations
*/
<T> CredentialDetails<T> regenerate(final CredentialName name);
/**
* Retrieve a credential using its ID, as returned in a write request.
*
* @param id the ID of the credential; must not be {@literal null}
* @param credentialType the type of the credential to be retrieved; must not be {@literal null}
* @param <T> the credential implementation type
* @return the details of the retrieved credential
*/
<T> CredentialDetails<T> getById(final String id, final Class<T> 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 <T> the credential implementation type
* @return the details of the retrieved credential
*/
<T> CredentialDetails<T> getByName(final CredentialName name, final Class<T> 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 <T> the credential implementation type
* @return the details of the retrieved credential, including history
*/
<T> List<CredentialDetails<T>> getByNameWithHistory(final CredentialName name, final Class<T> credentialType);
/**
* Retrieve a credential using its name, as passed to a write request.
* A collection of stored values for the named credential will be returned,
* with the specified number of historical values.
*
* @param name the name of the credential; must not be {@literal null}
* @param versions the number of historical versions to retrieve
* @param credentialType the type of credential expected to be returned
* @param <T> the credential implementation type
* @return the details of the retrieved credential, including history
*/
<T> List<CredentialDetails<T>> getByNameWithHistory(final CredentialName name, int versions,
final Class<T> 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<CredentialSummary> findByName(final CredentialName name);
/**
* Find a credential using a path.
*
* @param path the path to the credential; must not be {@literal null}
* @return a summary of the credential search results
*/
List<CredentialSummary> findByPath(final String path);
/**
* Delete a credential by its full name.
*
* @param name the name of the credential; must not be {@literal null}
*/
void deleteByName(final CredentialName 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
*/
List<CredentialPermission> getPermissions(final 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<CredentialPermission> addPermissions(final CredentialName name, final 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(final CredentialName name, final Actor actor);
/**
* Search the provided data structure of bound service credentials, looking for
* references to CredHub credentials. Any CredHub credentials found in the data
* structure will be replaced by the credential value stored in CredHub.
*
* Example:
*
* A JSON data structure parsed from a {@literal VCAP_SERVICES} environment
* variable might look like this if the service broker that provided the binding
* is integrated with CredHub:
*
* <pre>
* {@code
* {
* "service-offering": [{
* "credentials": {
* "credhub-ref": "((/c/service-broker/service-offering/1111-2222-3333-4444/credentials))"
* }
* "label": "service-offering",
* "name": "service-instance",
* "plan": "standard",
* "tags": ["
* "cloud-service"
* ]
* }]
* }
* }
* </pre>
*
* Assuming that CredHub has a credential with the name
* {@literal /c/service-broker/service-offering/1111-2222-3333-4444/credentials},
* passing the data structure above to this method would result in the
* {@literal credhub-ref} field being replaced by the credentials stored in CredHub:
*
* <pre>
* {@code
* {
* "service-offering": [{
* "credentials": {
* "url": "https://servicehost.example.com/",
* "username": "someuser",
* "password": "secret"
* }
* "label": "service-offering",
* "name": "service-instance",
* "plan": "standard",
* "tags": ["
* "cloud-service"
* ]
* }]
* }
* }
* </pre>
*
* @param serviceData a data structure of bound service credentials, as would be
* parsed from the {@literal VCAP_SERVICES} environment variable provided to
* applications running on Cloud Foundry
* @return the serviceData structure with CredHub references replaced by stored
* credential values
*/
ServicesData interpolateServiceData(final ServicesData serviceData);
CredHubInterpolationOperations interpolation();
/**
* Allow interaction with the configured {@link RestTemplate} not provided

View File

@@ -0,0 +1,55 @@
/*
* 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.
*/
package org.springframework.credhub.core;
import org.springframework.credhub.support.CredentialName;
import org.springframework.credhub.support.permissions.Actor;
import org.springframework.credhub.support.permissions.CredentialPermission;
import java.util.List;
/**
* Specifies the interactions with CredHub to add, retrieve, and delete permissions.
*
* @author Scott Frederick
*/
public interface CredHubPermissionsOperations {
/**
* 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
*/
List<CredentialPermission> getPermissions(final 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<CredentialPermission> addPermissions(final CredentialName name, final 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(final CredentialName name, final Actor actor);
}

View File

@@ -0,0 +1,102 @@
/*
* 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.
*/
package org.springframework.credhub.core;
import org.springframework.credhub.support.CredentialName;
import org.springframework.credhub.support.CredentialPermissions;
import org.springframework.credhub.support.permissions.Actor;
import org.springframework.credhub.support.permissions.CredentialPermission;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.web.client.RestOperations;
import java.util.List;
import static org.springframework.http.HttpMethod.POST;
/**
* Implements the main interaction with CredHub to add, retrieve,
* and delete permissions.
*
* @author Scott Frederick
*/
public class CredHubPermissionsTemplate implements CredHubPermissionsOperations {
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}";
private CredHubOperations credHubOperations;
/**
* Create a new {@link CredHubPermissionsTemplate}.
*
* @param credHubOperations the {@link CredHubOperations} to use for interactions with CredHub
*/
CredHubPermissionsTemplate(CredHubOperations credHubOperations) {
this.credHubOperations = credHubOperations;
}
@Override
public List<CredentialPermission> getPermissions(final CredentialName name) {
Assert.notNull(name, "credential name must not be null");
return credHubOperations.doWithRest(new RestOperationsCallback<List<CredentialPermission>>() {
@Override
public List<CredentialPermission> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialPermissions> response =
restOperations.getForEntity(PERMISSIONS_URL_QUERY,
CredentialPermissions.class, name.getName());
return response.getBody().getPermissions();
}
});
}
@Override
public List<CredentialPermission> addPermissions(final CredentialName name,
final CredentialPermission... permissions) {
Assert.notNull(name, "credential name must not be null");
final CredentialPermissions credentialPermissions = new CredentialPermissions(name, permissions);
return credHubOperations.doWithRest(new RestOperationsCallback<List<CredentialPermission>>() {
@Override
public List<CredentialPermission> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialPermissions> 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");
credHubOperations.doWithRest(new RestOperationsCallback<Void>() {
@Override
public Void doWithRestOperations(RestOperations restOperations) {
restOperations.delete(PERMISSIONS_ACTOR_URL_QUERY, name.getName(), actor.getIdentity());
return null;
}
});
}
}

View File

@@ -16,57 +16,17 @@
package org.springframework.credhub.core;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.permissions.Actor;
import org.springframework.credhub.support.permissions.CredentialPermission;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.util.Assert;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.HttpMethod.PUT;
/**
* Implements the main interaction with CredHub to save, retrieve,
* and delete credentials.
* Implements the main interaction with CredHub.
*
* @author Scott Frederick
*/
public class CredHubTemplate implements CredHubOperations {
static final String BASE_URL_PATH = "/api/v1/data";
static final String ID_URL_PATH = BASE_URL_PATH + "/{id}";
static final String NAME_URL_QUERY = BASE_URL_PATH + "?name={name}";
static final String NAME_URL_QUERY_CURRENT = NAME_URL_QUERY + "&current=true";
static final String NAME_URL_QUERY_VERSIONS = NAME_URL_QUERY + "&versions={versions}";
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";
static final String REGENERATE_URL_PATH = "/api/v1/regenerate";
private final RestTemplate restTemplate;
/**
@@ -98,279 +58,44 @@ public class CredHubTemplate implements CredHubOperations {
clientHttpRequestFactory);
}
/**
* Get the operations for saving, retrieving, and deleting credentials.
*
* @return the credentials operations
*/
@Override
public <T> CredentialDetails<T> write(final CredentialRequest<T> credentialRequest) {
Assert.notNull(credentialRequest, "credentialRequest must not be null");
final ParameterizedTypeReference<CredentialDetails<T>> ref =
new ParameterizedTypeReference<CredentialDetails<T>>() {};
return doWithRest(new RestOperationsCallback<CredentialDetails<T>>() {
@Override
public CredentialDetails<T> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDetails<T>> response =
restOperations.exchange(BASE_URL_PATH, PUT,
new HttpEntity<>(credentialRequest), ref);
throwExceptionOnError(response);
return response.getBody();
}
});
public CredHubCredentialsOperations credentials() {
return new CredHubCredentialsTemplate(this);
}
/**
* Get the operations for adding, retrieving, and deleting permissions from a credential.
*
* @return the permissions operations
*/
@Override
public <T, P> CredentialDetails<T> generate(final ParametersRequest<P> parametersRequest) {
Assert.notNull(parametersRequest, "parametersRequest must not be null");
final ParameterizedTypeReference<CredentialDetails<T>> ref =
new ParameterizedTypeReference<CredentialDetails<T>>() {};
return doWithRest(new RestOperationsCallback<CredentialDetails<T>>() {
@Override
public CredentialDetails<T> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDetails<T>> response =
restOperations.exchange(BASE_URL_PATH, POST,
new HttpEntity<>(parametersRequest), ref);
throwExceptionOnError(response);
return response.getBody();
}
});
public CredHubPermissionsOperations permissions() {
return new CredHubPermissionsTemplate(this);
}
/**
* Get the operations interpolating service binding credentials.
*
* @return the interpolation operations
*/
@Override
public <T> CredentialDetails<T> regenerate(final CredentialName name) {
Assert.notNull(name, "credential name must not be null");
final ParameterizedTypeReference<CredentialDetails<T>> ref =
new ParameterizedTypeReference<CredentialDetails<T>>() {};
return doWithRest(new RestOperationsCallback<CredentialDetails<T>>() {
@Override
public CredentialDetails<T> doWithRestOperations(RestOperations restOperations) {
Map<String, Object> request = new HashMap<>(1);
request.put("name", name.getName());
ResponseEntity<CredentialDetails<T>> response =
restOperations.exchange(REGENERATE_URL_PATH, POST,
new HttpEntity<>(request), ref);
throwExceptionOnError(response);
return response.getBody();
}
});
}
@Override
public <T> CredentialDetails<T> getById(final String id, final Class<T> credentialType) {
Assert.notNull(id, "credential id must not be null");
Assert.notNull(credentialType, "credential type must not be null");
final ParameterizedTypeReference<CredentialDetails<T>> ref =
new ParameterizedTypeReference<CredentialDetails<T>>() {};
return doWithRest(new RestOperationsCallback<CredentialDetails<T>>() {
@Override
public CredentialDetails<T> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDetails<T>> response =
restOperations.exchange(ID_URL_PATH, GET, null, ref, id);
throwExceptionOnError(response);
return response.getBody();
}
});
}
@Override
public <T> CredentialDetails<T> getByName(final CredentialName name, final Class<T> credentialType) {
Assert.notNull(name, "credential name must not be null");
Assert.notNull(credentialType, "credential type must not be null");
final ParameterizedTypeReference<CredentialDetailsData<T>> ref =
new ParameterizedTypeReference<CredentialDetailsData<T>>() {};
return doWithRest(new RestOperationsCallback<CredentialDetails<T>>() {
@Override
public CredentialDetails<T> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDetailsData<T>> response =
restOperations.exchange(NAME_URL_QUERY_CURRENT, GET, null, ref, name.getName());
throwExceptionOnError(response);
return response.getBody().getData().get(0);
}
});
}
@Override
public <T> List<CredentialDetails<T>> getByNameWithHistory(final CredentialName name, final Class<T> credentialType) {
Assert.notNull(name, "credential name must not be null");
Assert.notNull(credentialType, "credential type must not be null");
final ParameterizedTypeReference<CredentialDetailsData<T>> ref =
new ParameterizedTypeReference<CredentialDetailsData<T>>() {};
return doWithRest(new RestOperationsCallback<List<CredentialDetails<T>>>() {
@Override
public List<CredentialDetails<T>> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDetailsData<T>> response =
restOperations.exchange(NAME_URL_QUERY, GET, null, ref, name.getName());
throwExceptionOnError(response);
return response.getBody().getData();
}
});
}
@Override
public <T> List<CredentialDetails<T>> getByNameWithHistory(final CredentialName name, final int versions,
final Class<T> credentialType) {
Assert.notNull(name, "credential name must not be null");
Assert.notNull(credentialType, "credential type must not be null");
final ParameterizedTypeReference<CredentialDetailsData<T>> ref =
new ParameterizedTypeReference<CredentialDetailsData<T>>() {};
return doWithRest(new RestOperationsCallback<List<CredentialDetails<T>>>() {
@Override
public List<CredentialDetails<T>> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDetailsData<T>> response =
restOperations.exchange(NAME_URL_QUERY_VERSIONS, GET, null, ref,
name.getName(), versions);
throwExceptionOnError(response);
return response.getBody().getData();
}
});
}
@Override
public List<CredentialSummary> findByName(final CredentialName name) {
Assert.notNull(name, "credential name must not be null");
return doWithRest(new RestOperationsCallback<List<CredentialSummary>>() {
@Override
public List<CredentialSummary> doWithRestOperations(
RestOperations restOperations) {
ResponseEntity<CredentialSummaryData> response = restOperations
.getForEntity(NAME_LIKE_URL_QUERY,
CredentialSummaryData.class, name.getName());
throwExceptionOnError(response);
return response.getBody().getCredentials();
}
});
}
@Override
public List<CredentialSummary> findByPath(final String path) {
Assert.notNull(path, "credential path must not be null");
return doWithRest(new RestOperationsCallback<List<CredentialSummary>>() {
@Override
public List<CredentialSummary> doWithRestOperations(
RestOperations restOperations) {
ResponseEntity<CredentialSummaryData> response = restOperations
.getForEntity(PATH_URL_QUERY, CredentialSummaryData.class,
path);
throwExceptionOnError(response);
return response.getBody().getCredentials();
}
});
}
@Override
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<Void>() {
@Override
public Void doWithRestOperations(RestOperations restOperations) {
restOperations.delete(NAME_URL_QUERY, name1);
return null;
}
});
}
@Override
public List<CredentialPermission> getPermissions(final CredentialName name) {
Assert.notNull(name, "credential name must not be null");
return doWithRest(new RestOperationsCallback<List<CredentialPermission>>() {
@Override
public List<CredentialPermission> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialPermissions> response =
restOperations.getForEntity(PERMISSIONS_URL_QUERY,
CredentialPermissions.class, name.getName());
return response.getBody().getPermissions();
}
});
}
@Override
public List<CredentialPermission> addPermissions(final CredentialName name,
final CredentialPermission... permissions) {
Assert.notNull(name, "credential name must not be null");
final CredentialPermissions credentialPermissions = new CredentialPermissions(name, permissions);
return doWithRest(new RestOperationsCallback<List<CredentialPermission>>() {
@Override
public List<CredentialPermission> doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialPermissions> 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<Void>() {
@Override
public Void doWithRestOperations(RestOperations restOperations) {
restOperations.delete(PERMISSIONS_ACTOR_URL_QUERY, name.getName(), actor.getIdentity());
return null;
}
});
}
@Override
public ServicesData interpolateServiceData(final ServicesData serviceData) {
Assert.notNull(serviceData, "serviceData must not be null");
return doWithRest(new RestOperationsCallback<ServicesData>() {
@Override
public ServicesData doWithRestOperations(RestOperations restOperations) {
ResponseEntity<ServicesData> response = restOperations
.exchange(INTERPOLATE_URL_PATH, POST,
new HttpEntity<>(serviceData), ServicesData.class);
throwExceptionOnError(response);
return response.getBody();
}
});
public CredHubInterpolationOperations interpolation() {
return new CredHubInterpolationTemplate(this);
}
/**
* Allow interaction with the configured {@link RestTemplate} not provided
* by other methods.
*
* @param callback wrapper for the callback method
* @param <T> the credential implementation type
* @return the return value from the callback method
*/
@Override
public <T> T doWithRest(RestOperationsCallback<T> callback) {
Assert.notNull(callback, "callback must not be null");
@@ -382,16 +107,4 @@ public class CredHubTemplate implements CredHubOperations {
throw new CredHubException(e);
}
}
/**
* Helper method to throw an appropriate exception if a request to CredHub
* returns with an error code.
*
* @param response a {@link ResponseEntity} returned from {@link RestTemplate}
*/
private void throwExceptionOnError(ResponseEntity<?> response) {
if (!response.getStatusCode().equals(HttpStatus.OK)) {
throw new CredHubException(response.getStatusCode());
}
}
}

View File

@@ -39,7 +39,7 @@ public class CredHubClientUnitTests {
private ClientHttpRequestFactory clientHttpRequestFactory;
@Test
public void restTemplateIsCreated() throws Exception {
public void restTemplateIsCreated() {
RestTemplate restTemplate = CredHubClient.createRestTemplate(CREDHUB_URI,
clientHttpRequestFactory);

View File

@@ -34,13 +34,13 @@ import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import static org.springframework.credhub.core.CredHubTemplate.NAME_LIKE_URL_QUERY;
import static org.springframework.credhub.core.CredHubTemplate.PATH_URL_QUERY;
import static org.springframework.credhub.core.CredHubCredentialsTemplate.NAME_LIKE_URL_QUERY;
import static org.springframework.credhub.core.CredHubCredentialsTemplate.PATH_URL_QUERY;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
@RunWith(Theories.class)
public class CredHubTemplateSummaryResponseUnitTests extends CredHubTemplateUnitTestsBase {
public class CredHubCredentialsTemplateSummaryUnitTests extends CredHubCredentialsTemplateUnitTestsBase {
@DataPoint("responses")
public static ResponseEntity<CredentialSummaryData> successfulResponse =
new ResponseEntity<>(new CredentialSummaryData(new CredentialSummary(NAME)), OK);

View File

@@ -0,0 +1,35 @@
/*
* 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.
*/
package org.springframework.credhub.core;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.verify;
import static org.springframework.credhub.core.CredHubCredentialsTemplate.NAME_URL_QUERY;
@RunWith(MockitoJUnitRunner.class)
public class CredHubCredentialsTemplateUnitTests extends CredHubCredentialsTemplateUnitTestsBase {
@Test
public void deleteByName() {
credHubTemplate.deleteByName(NAME);
verify(restTemplate).delete(NAME_URL_QUERY, NAME.getName());
}
}

View File

@@ -26,7 +26,7 @@ import org.mockito.quality.Strictness;
import org.springframework.credhub.support.SimpleCredentialName;
import org.springframework.web.client.RestTemplate;
public abstract class CredHubTemplateUnitTestsBase {
public abstract class CredHubCredentialsTemplateUnitTestsBase {
protected static final SimpleCredentialName NAME = new SimpleCredentialName("example", "credential");
@Rule
@@ -35,10 +35,10 @@ public abstract class CredHubTemplateUnitTestsBase {
@Mock
protected RestTemplate restTemplate;
protected CredHubTemplate credHubTemplate;
protected CredHubCredentialsOperations credHubTemplate;
@Before
public void setUpCredHubTemplateUnitTests() {
credHubTemplate = new CredHubTemplate(restTemplate);
credHubTemplate = new CredHubTemplate(restTemplate).credentials();
}
}

View File

@@ -0,0 +1,104 @@
/*
* 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.
*/
package org.springframework.credhub.core;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.junit.MockitoRule;
import org.mockito.quality.Strictness;
import org.springframework.credhub.support.ServiceInstanceCredentialName;
import org.springframework.credhub.support.ServicesData;
import org.springframework.credhub.support.utils.JsonUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
import static org.springframework.credhub.core.CredHubInterpolationTemplate.INTERPOLATE_URL_PATH;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.HttpStatus.OK;
@RunWith(MockitoJUnitRunner.class)
public class CredHubInterpolationTemplateUnitTests {
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
@Mock
private RestTemplate restTemplate;
private CredHubInterpolationOperations credHubTemplate;
@Before
public void setUpCredHubTemplateUnitTests() {
credHubTemplate = new CredHubTemplate(restTemplate).interpolation();
}
@Test
public void interpolateServiceData() throws IOException {
ServiceInstanceCredentialName credentialName = ServiceInstanceCredentialName.builder()
.serviceBrokerName("service-broker")
.serviceOfferingName("service-offering")
.serviceBindingId("1111-1111-1111-111")
.credentialName("credential_json")
.build();
ServicesData vcapServices = buildVcapServices(credentialName.getName());
ServicesData expectedResponse = new ServicesData();
when(restTemplate.exchange(INTERPOLATE_URL_PATH, POST,
new HttpEntity<>(vcapServices), ServicesData.class))
.thenReturn(new ResponseEntity<>(expectedResponse, OK));
ServicesData response = credHubTemplate.interpolateServiceData(vcapServices);
assertThat(response, equalTo(expectedResponse));
}
private ServicesData buildVcapServices(String credHubReferenceName) throws IOException {
String vcapServices = "{" +
" \"service-offering\": [" +
" {" +
" \"credentials\": {" +
" \"credhub-ref\": \"((" + credHubReferenceName + "))\"" +
" }," +
" \"label\": \"service-offering\"," +
" \"name\": \"service-instance\"," +
" \"plan\": \"standard\"," +
" \"tags\": [" +
" \"cloud-service\"" +
" ]," +
" \"volume_mounts\": []" +
" }" +
" ]" +
"}";
ObjectMapper mapper = JsonUtils.buildObjectMapper();
return mapper.readValue(vcapServices, ServicesData.class);
}
}

View File

@@ -16,45 +16,46 @@
package org.springframework.credhub.core;
import java.io.IOException;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.credhub.support.CredentialPermissions;
import org.springframework.credhub.support.SimpleCredentialName;
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.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.util.List;
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.credhub.core.CredHubPermissionsTemplate.PERMISSIONS_ACTOR_URL_QUERY;
import static org.springframework.credhub.core.CredHubPermissionsTemplate.PERMISSIONS_URL_PATH;
import static org.springframework.credhub.core.CredHubPermissionsTemplate.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);
public class CredHubPermissionsTemplateUnitTests {
private static final SimpleCredentialName NAME = new SimpleCredentialName("example", "credential");
verify(restTemplate).delete(NAME_URL_QUERY, NAME.getName());
@Mock
private RestTemplate restTemplate;
private CredHubPermissionsOperations credHubTemplate;
@Before
public void setUpCredHubTemplateUnitTests() {
credHubTemplate = new CredHubTemplate(restTemplate).permissions();
}
@Test
@@ -75,7 +76,7 @@ public class CredHubTemplateUnitTests extends CredHubTemplateUnitTestsBase {
);
when(restTemplate.getForEntity(PERMISSIONS_URL_QUERY, CredentialPermissions.class, NAME.getName()))
.thenReturn(new ResponseEntity<CredentialPermissions>(expectedResponse, OK));
.thenReturn(new ResponseEntity<>(expectedResponse, OK));
List<CredentialPermission> response = credHubTemplate.getPermissions(NAME);
@@ -102,8 +103,8 @@ public class CredHubTemplateUnitTests extends CredHubTemplateUnitTestsBase {
CredentialPermissions expectedResponse = new CredentialPermissions(NAME, permission1, permission2);
when(restTemplate.exchange(PERMISSIONS_URL_PATH, POST,
new HttpEntity<CredentialPermissions>(expectedResponse), CredentialPermissions.class))
.thenReturn(new ResponseEntity<CredentialPermissions>(expectedResponse, OK));
new HttpEntity<>(expectedResponse), CredentialPermissions.class))
.thenReturn(new ResponseEntity<>(expectedResponse, OK));
List<CredentialPermission> response = credHubTemplate.addPermissions(NAME, permission1, permission2);
@@ -118,49 +119,4 @@ public class CredHubTemplateUnitTests extends CredHubTemplateUnitTestsBase {
verify(restTemplate).delete(PERMISSIONS_ACTOR_URL_QUERY, NAME.getName(), ActorType.APP + ":appid1");
}
@Test
public void interpolateServiceData() throws IOException {
ServiceInstanceCredentialName credentialName = ServiceInstanceCredentialName.builder()
.serviceBrokerName("service-broker")
.serviceOfferingName("service-offering")
.serviceBindingId("1111-1111-1111-111")
.credentialName("credential_json")
.build();
ServicesData vcapServices = buildVcapServices(credentialName.getName());
ServicesData expectedResponse = new ServicesData();
when(restTemplate.exchange(INTERPOLATE_URL_PATH, POST,
new HttpEntity<ServicesData>(vcapServices), ServicesData.class))
.thenReturn(new ResponseEntity<ServicesData>(expectedResponse, OK));
ServicesData response = credHubTemplate.interpolateServiceData(vcapServices);
assertThat(response, equalTo(expectedResponse));
}
private ServicesData buildVcapServices(String credHubReferenceName) throws IOException {
String vcapServices = "{" +
" \"service-offering\": [" +
" {" +
" \"credentials\": {" +
" \"credhub-ref\": \"((" + credHubReferenceName + "))\"" +
" }," +
" \"label\": \"service-offering\"," +
" \"name\": \"service-instance\"," +
" \"plan\": \"standard\"," +
" \"tags\": [" +
" \"cloud-service\"" +
" ]," +
" \"volume_mounts\": []" +
" }" +
" ]" +
"}";
ObjectMapper mapper = JsonUtils.buildObjectMapper();
return mapper.readValue(vcapServices, ServicesData.class);
}
}

View File

@@ -40,12 +40,12 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.when;
import static org.springframework.credhub.core.CredHubTemplate.BASE_URL_PATH;
import static org.springframework.credhub.core.CredHubTemplate.ID_URL_PATH;
import static org.springframework.credhub.core.CredHubTemplate.NAME_URL_QUERY;
import static org.springframework.credhub.core.CredHubTemplate.NAME_URL_QUERY_CURRENT;
import static org.springframework.credhub.core.CredHubTemplate.NAME_URL_QUERY_VERSIONS;
import static org.springframework.credhub.core.CredHubTemplate.REGENERATE_URL_PATH;
import static org.springframework.credhub.core.CredHubCredentialsTemplate.BASE_URL_PATH;
import static org.springframework.credhub.core.CredHubCredentialsTemplate.ID_URL_PATH;
import static org.springframework.credhub.core.CredHubCredentialsTemplate.NAME_URL_QUERY;
import static org.springframework.credhub.core.CredHubCredentialsTemplate.NAME_URL_QUERY_CURRENT;
import static org.springframework.credhub.core.CredHubCredentialsTemplate.NAME_URL_QUERY_VERSIONS;
import static org.springframework.credhub.core.CredHubCredentialsTemplate.REGENERATE_URL_PATH;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.HttpMethod.PUT;
@@ -53,7 +53,7 @@ import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
@SuppressWarnings("unchecked")
public abstract class CredHubTemplateDetailUnitTestsBase<T, P> extends CredHubTemplateUnitTestsBase {
public abstract class CredHubTemplateDetailUnitTestsBase<T, P> extends CredHubCredentialsTemplateUnitTestsBase {
private static final String CREDENTIAL_ID = "1111-1111-1111-1111";
protected abstract Class<T> getType();