Removing security-credhub module
This commit is contained in:
@@ -31,6 +31,5 @@ include "spring-cloud-app-broker-core"
|
||||
include "spring-cloud-app-broker-autoconfigure"
|
||||
include "spring-cloud-app-broker-integration-tests"
|
||||
include "spring-cloud-app-broker-acceptance-tests"
|
||||
include "spring-cloud-app-broker-security-credhub"
|
||||
include "spring-cloud-starter-app-broker"
|
||||
include "spring-cloud-starter-app-broker-cloudfoundry"
|
||||
|
||||
@@ -31,11 +31,9 @@ dependencies {
|
||||
api project(":spring-cloud-app-broker-core")
|
||||
api project(":spring-cloud-app-broker-deployer")
|
||||
api project(":spring-cloud-app-broker-deployer-cloudfoundry")
|
||||
api project(":spring-cloud-app-broker-security-credhub")
|
||||
api "org.springframework.boot:spring-boot-starter"
|
||||
api "org.cloudfoundry:cloudfoundry-client-reactor:${cfJavaClientVersion}"
|
||||
api "org.cloudfoundry:cloudfoundry-operations:${cfJavaClientVersion}"
|
||||
api "org.springframework.credhub:spring-credhub-starter:${springCredhubVersion}"
|
||||
|
||||
testImplementation "org.springframework.boot:spring-boot-starter-test"
|
||||
testImplementation "org.springframework.boot:spring-boot-starter-webflux"
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.autoconfigure;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.CredHubCredentialsGenerator;
|
||||
import org.springframework.cloud.appbroker.service.CreateServiceInstanceAppBindingWorkflow;
|
||||
import org.springframework.cloud.appbroker.service.DeleteServiceInstanceBindingWorkflow;
|
||||
import org.springframework.cloud.appbroker.workflow.binding.CredHubPersistingCreateServiceInstanceAppBindingWorkflow;
|
||||
import org.springframework.cloud.appbroker.workflow.binding.CredHubPersistingDeleteServiceInstanceBindingWorkflow;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.credhub.autoconfig.CredHubTemplateAutoConfiguration;
|
||||
import org.springframework.credhub.core.ReactiveCredHubOperations;
|
||||
|
||||
/**
|
||||
* CredHub auto-configuration
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureBefore(AppBrokerAutoConfiguration.class)
|
||||
@AutoConfigureAfter(CredHubTemplateAutoConfiguration.class)
|
||||
@ConditionalOnClass(ReactiveCredHubOperations.class)
|
||||
@ConditionalOnBean(ReactiveCredHubOperations.class)
|
||||
public class CredHubAutoConfiguration {
|
||||
|
||||
@Value("${spring.application.name}")
|
||||
private String appName;
|
||||
|
||||
/**
|
||||
* Provide a {@link CreateServiceInstanceAppBindingWorkflow} bean
|
||||
*
|
||||
* @param credHubOperations the ReactiveCredHubOperations bean
|
||||
* @return the bean
|
||||
*/
|
||||
@Bean
|
||||
public CreateServiceInstanceAppBindingWorkflow credhubPersistingCreateServiceInstanceAppBindingWorkflow(
|
||||
ReactiveCredHubOperations credHubOperations) {
|
||||
return new CredHubPersistingCreateServiceInstanceAppBindingWorkflow(credHubOperations, appName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a {@link DeleteServiceInstanceBindingWorkflow} bean
|
||||
*
|
||||
* @param credHubOperations the ReactiveCredHubOperations bean
|
||||
* @return the bean
|
||||
*/
|
||||
@Bean
|
||||
public DeleteServiceInstanceBindingWorkflow credhubPersistingDeleteServiceInstanceAppBindingWorkflow(
|
||||
ReactiveCredHubOperations credHubOperations) {
|
||||
return new CredHubPersistingDeleteServiceInstanceBindingWorkflow(credHubOperations, appName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a {@link CredHubCredentialsGenerator} bean
|
||||
*
|
||||
* @param credHubOperations the ReactiveCredHubOperations bean
|
||||
* @return the bean
|
||||
*/
|
||||
@Bean
|
||||
public CredHubCredentialsGenerator credHubCredentialsGenerator(ReactiveCredHubOperations credHubOperations) {
|
||||
return new CredHubCredentialsGenerator(credHubOperations);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +1,2 @@
|
||||
org.springframework.cloud.appbroker.autoconfigure.AppBrokerAutoConfiguration
|
||||
org.springframework.cloud.appbroker.autoconfigure.CloudFoundryAppDeployerAutoConfiguration
|
||||
org.springframework.cloud.appbroker.autoconfigure.CredHubAutoConfiguration
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.autoconfigure;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.CredHubCredentialsGenerator;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.CredentialGenerator;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.SimpleCredentialGenerator;
|
||||
import org.springframework.cloud.appbroker.workflow.binding.CredHubPersistingCreateServiceInstanceAppBindingWorkflow;
|
||||
import org.springframework.cloud.appbroker.workflow.binding.CredHubPersistingDeleteServiceInstanceBindingWorkflow;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.credhub.core.ReactiveCredHubOperations;
|
||||
import org.springframework.credhub.core.ReactiveCredHubTemplate;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class CredHubAutoConfigurationTest {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(
|
||||
CloudFoundryAppDeployerAutoConfiguration.class,
|
||||
AppBrokerAutoConfiguration.class,
|
||||
CredHubAutoConfiguration.class
|
||||
))
|
||||
.withUserConfiguration(CredHubConfiguration.class)
|
||||
.withPropertyValues(
|
||||
"spring.cloud.appbroker.deployer.cloudfoundry.api-host=https://api.example.local",
|
||||
"spring.cloud.appbroker.deployer.cloudfoundry.username=user",
|
||||
"spring.cloud.appbroker.deployer.cloudfoundry.password=secret"
|
||||
);
|
||||
|
||||
@Test
|
||||
void servicesAreNotCreatedWithoutCredHubOnClasspath() {
|
||||
contextRunner
|
||||
.withClassLoader(new FilteredClassLoader(ReactiveCredHubOperations.class))
|
||||
.run((context) -> {
|
||||
assertThat(context)
|
||||
.hasSingleBean(CredentialGenerator.class)
|
||||
.getBean(CredentialGenerator.class)
|
||||
.isExactlyInstanceOf(SimpleCredentialGenerator.class);
|
||||
|
||||
assertThat(context)
|
||||
.doesNotHaveBean(CredHubPersistingCreateServiceInstanceAppBindingWorkflow.class)
|
||||
.doesNotHaveBean(CredHubPersistingDeleteServiceInstanceBindingWorkflow.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void servicesAreCreatedWithCredHubConfigured() {
|
||||
contextRunner
|
||||
.run((context) -> {
|
||||
assertThat(context)
|
||||
.hasSingleBean(CredentialGenerator.class)
|
||||
.getBean(CredentialGenerator.class)
|
||||
.isExactlyInstanceOf(CredHubCredentialsGenerator.class);
|
||||
|
||||
assertThat(context)
|
||||
.hasSingleBean(CredHubPersistingCreateServiceInstanceAppBindingWorkflow.class)
|
||||
.hasSingleBean(CredHubPersistingDeleteServiceInstanceBindingWorkflow.class);
|
||||
});
|
||||
}
|
||||
|
||||
@TestConfiguration
|
||||
public static class CredHubConfiguration {
|
||||
|
||||
@Bean
|
||||
public ReactiveCredHubOperations credHubOperations() {
|
||||
return new ReactiveCredHubTemplate(WebClient.create());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.integration;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.CredHubStubFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.OpenServiceBrokerApiFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.TestBindingCredentialsProviderFixture;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.springframework.cloud.appbroker.integration.CreateBindingWithCredHubComponentTest.APP_NAME;
|
||||
|
||||
@TestPropertySource(properties = {
|
||||
"spring.cloud.appbroker.services[0].service-name=example",
|
||||
"spring.cloud.appbroker.services[0].plan-name=standard",
|
||||
"spring.cloud.appbroker.services[0].apps[0].path=classpath:demo.jar",
|
||||
"spring.cloud.appbroker.services[0].apps[0].name=" + APP_NAME,
|
||||
|
||||
"spring.credhub.url=http://localhost:8888"
|
||||
})
|
||||
class CreateBindingWithCredHubComponentTest extends WiremockComponentTest {
|
||||
|
||||
protected static final String APP_NAME = "create-binding-credhub";
|
||||
|
||||
private static final String SERVICE_INSTANCE_ID = "instance-id";
|
||||
|
||||
private static final String BINDING_ID = "binding-id";
|
||||
|
||||
private static final String CREDENTIAL_NAME = "credentials-json";
|
||||
|
||||
private static final String APP_ID = "app-id";
|
||||
|
||||
@Autowired
|
||||
private OpenServiceBrokerApiFixture brokerFixture;
|
||||
|
||||
@Autowired
|
||||
private CredHubStubFixture credHubFixture;
|
||||
|
||||
@Autowired
|
||||
private TestBindingCredentialsProviderFixture bindingFixture;
|
||||
|
||||
@Value("${spring.application.name}")
|
||||
private String brokerAppName;
|
||||
|
||||
@Value("${spring.cloud.openservicebroker.catalog.services[0].id}")
|
||||
private String serviceDefinitionId;
|
||||
|
||||
@Test
|
||||
void createAppBindingWithCredHub() {
|
||||
String credentialName = credHubFixture.bindingCredentialName(brokerAppName, serviceDefinitionId,
|
||||
BINDING_ID, CREDENTIAL_NAME);
|
||||
|
||||
credHubFixture.stubWriteCredential(credentialName,
|
||||
matchingJsonPath("$.[?(@.value.credential1 == '" +
|
||||
bindingFixture.getCredentials().get("credential1") +
|
||||
"')]"),
|
||||
matchingJsonPath("$.[?(@.value.credential2 == '" +
|
||||
bindingFixture.getCredentials().get("credential2") +
|
||||
"')]"));
|
||||
|
||||
credHubFixture.stubAddAppPermission(credentialName, "mtls-app:" + APP_ID);
|
||||
|
||||
// when a service binding is created
|
||||
given(brokerFixture.serviceAppBindingRequest())
|
||||
.when()
|
||||
.put(brokerFixture.createBindingUrl(), SERVICE_INSTANCE_ID, BINDING_ID)
|
||||
.then()
|
||||
.statusCode(HttpStatus.CREATED.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createServiceKeyWithCredHub() {
|
||||
String credentialName = credHubFixture.bindingCredentialName(brokerAppName, serviceDefinitionId,
|
||||
BINDING_ID, CREDENTIAL_NAME);
|
||||
|
||||
credHubFixture.stubWriteCredential(credentialName,
|
||||
matchingJsonPath("$.[?(@.value.credential1 == '" +
|
||||
bindingFixture.getCredentials().get("credential1") +
|
||||
"')]"),
|
||||
matchingJsonPath("$.[?(@.value.credential2 == '" +
|
||||
bindingFixture.getCredentials().get("credential2") +
|
||||
"')]"));
|
||||
|
||||
credHubFixture.stubAddAppPermission(credentialName, "uaa-client:service-key-client-id");
|
||||
|
||||
// when a service binding is created
|
||||
given(brokerFixture.serviceKeyRequest())
|
||||
.when()
|
||||
.put(brokerFixture.createBindingUrl(), SERVICE_INSTANCE_ID, BINDING_ID)
|
||||
.then()
|
||||
.statusCode(HttpStatus.CREATED.value());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.integration;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.CloudControllerStubFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.CredHubStubFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.OpenServiceBrokerApiFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.UaaStubFixture;
|
||||
import org.springframework.cloud.servicebroker.model.instance.OperationState;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.springframework.cloud.appbroker.integration.CreateInstanceWithCredHubCredentialsComponentTest.APP_NAME;
|
||||
|
||||
@TestPropertySource(properties = {
|
||||
"spring.cloud.appbroker.services[0].service-name=example",
|
||||
"spring.cloud.appbroker.services[0].plan-name=standard",
|
||||
"spring.cloud.appbroker.services[0].apps[0].path=classpath:demo.jar",
|
||||
"spring.cloud.appbroker.services[0].apps[0].name=" + APP_NAME,
|
||||
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[0].name=SpringSecurityBasicAuth",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[0].args.length=14",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[0].args.include-uppercase-alpha=true",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[0].args.include-lowercase-alpha=true",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[0].args.include-numeric=false",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[0].args.include-special=false",
|
||||
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].name=SpringSecurityOAuth2",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.registration=example-app-client",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.client-id=test-client",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.grant-types=[\"client_credentials\"]",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.length=12",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.include-uppercase-alpha=true",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.include-lowercase-alpha=true",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.include-numeric=false",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.include-special=false",
|
||||
|
||||
"spring.credhub.url=http://localhost:8888"
|
||||
})
|
||||
@Disabled
|
||||
// See https://github.com/spring-cloud/spring-cloud-app-broker/issues/315
|
||||
class CreateInstanceWithCredHubCredentialsComponentTest extends WiremockComponentTest {
|
||||
|
||||
protected static final String APP_NAME = "app-with-credentials";
|
||||
|
||||
private static final String SERVICE_INSTANCE_ID = "instance-id";
|
||||
|
||||
@Autowired
|
||||
private OpenServiceBrokerApiFixture brokerFixture;
|
||||
|
||||
@Autowired
|
||||
private CloudControllerStubFixture cloudControllerFixture;
|
||||
|
||||
@Autowired
|
||||
private UaaStubFixture uaaFixture;
|
||||
|
||||
@Autowired
|
||||
private CredHubStubFixture credHubFixture;
|
||||
|
||||
@Test
|
||||
void pushAppWithCredentials() {
|
||||
cloudControllerFixture.stubAppDoesNotExist(APP_NAME);
|
||||
cloudControllerFixture.stubPushApp(APP_NAME);
|
||||
|
||||
uaaFixture.stubCreateClient("test-client");
|
||||
|
||||
credHubFixture.stubGenerateUser(APP_NAME, SERVICE_INSTANCE_ID, "basic", 14);
|
||||
credHubFixture.stubGeneratePassword(APP_NAME, SERVICE_INSTANCE_ID, "oauth2", 12);
|
||||
|
||||
// when a service instance is created
|
||||
given(brokerFixture.serviceInstanceRequest())
|
||||
.when()
|
||||
.put(brokerFixture.createServiceInstanceUrl(), SERVICE_INSTANCE_ID)
|
||||
.then()
|
||||
.statusCode(HttpStatus.ACCEPTED.value());
|
||||
|
||||
// when the "last_operation" API is polled
|
||||
given(brokerFixture.serviceInstanceRequest())
|
||||
.when()
|
||||
.get(brokerFixture.getLastInstanceOperationUrl(), SERVICE_INSTANCE_ID)
|
||||
.then()
|
||||
.statusCode(HttpStatus.OK.value())
|
||||
.body("state", is(equalTo(OperationState.IN_PROGRESS.toString())));
|
||||
|
||||
String state = brokerFixture.waitForAsyncOperationComplete(SERVICE_INSTANCE_ID);
|
||||
assertThat(state).isEqualTo(OperationState.SUCCEEDED.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.integration;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.CredHubStubFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.OpenServiceBrokerApiFixture;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.springframework.cloud.appbroker.integration.DeleteBindingWithCredHubComponentTest.APP_NAME;
|
||||
|
||||
@TestPropertySource(properties = {
|
||||
"spring.cloud.appbroker.services[0].service-name=example",
|
||||
"spring.cloud.appbroker.services[0].plan-name=standard",
|
||||
"spring.cloud.appbroker.services[0].apps[0].path=classpath:demo.jar",
|
||||
"spring.cloud.appbroker.services[0].apps[0].name=" + APP_NAME,
|
||||
|
||||
"spring.credhub.url=http://localhost:8888"
|
||||
})
|
||||
class DeleteBindingWithCredHubComponentTest extends WiremockComponentTest {
|
||||
|
||||
protected static final String APP_NAME = "delete-binding-credhub";
|
||||
|
||||
private static final String SERVICE_INSTANCE_ID = "instance-id";
|
||||
|
||||
private static final String BINDING_ID = "binding-id";
|
||||
|
||||
private static final String CREDENTIAL_NAME = "credentials-json";
|
||||
|
||||
@Autowired
|
||||
private OpenServiceBrokerApiFixture brokerFixture;
|
||||
|
||||
@Autowired
|
||||
private CredHubStubFixture credHubFixture;
|
||||
|
||||
@Value("${spring.application.name}")
|
||||
private String brokerAppName;
|
||||
|
||||
@Value("${spring.cloud.openservicebroker.catalog.services[0].id}")
|
||||
private String serviceDefinitionId;
|
||||
|
||||
@Test
|
||||
void deleteAppBindingWithCredHub() {
|
||||
String credentialName = credHubFixture.bindingCredentialName(brokerAppName, serviceDefinitionId,
|
||||
BINDING_ID, CREDENTIAL_NAME);
|
||||
|
||||
credHubFixture.stubFindCredential(credentialName);
|
||||
credHubFixture.stubDeleteCredential(credentialName);
|
||||
credHubFixture.stubDeletePermission(credentialName);
|
||||
|
||||
// when a service binding is deleted
|
||||
given(brokerFixture.serviceAppBindingRequest())
|
||||
.when()
|
||||
.delete(brokerFixture.deleteBindingUrl(), SERVICE_INSTANCE_ID, BINDING_ID)
|
||||
.then()
|
||||
.statusCode(HttpStatus.OK.value());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.integration;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.CloudControllerStubFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.CredHubStubFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.OpenServiceBrokerApiFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.UaaStubFixture;
|
||||
import org.springframework.cloud.servicebroker.model.instance.OperationState;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.springframework.cloud.appbroker.integration.DeleteInstanceWithCredHubCredentialsComponentTest.APP_NAME;
|
||||
|
||||
@TestPropertySource(properties = {
|
||||
"spring.cloud.appbroker.services[0].service-name=example",
|
||||
"spring.cloud.appbroker.services[0].plan-name=standard",
|
||||
"spring.cloud.appbroker.services[0].apps[0].path=classpath:demo.jar",
|
||||
"spring.cloud.appbroker.services[0].apps[0].name=" + APP_NAME,
|
||||
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[0].name=SpringSecurityBasicAuth",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[0].args.length=14",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[0].args.include-uppercase-alpha=true",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[0].args.include-lowercase-alpha=true",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[0].args.include-numeric=false",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[0].args.include-special=false",
|
||||
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].name=SpringSecurityOAuth2",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.registration=example-app-client",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.client-id=test-client",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.grant-types=[\"client_credentials\"]",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.length=12",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.include-uppercase-alpha=true",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.include-lowercase-alpha=true",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.include-numeric=false",
|
||||
"spring.cloud.appbroker.services[0].apps[0].credential-providers[1].args.include-special=false",
|
||||
|
||||
"spring.credhub.url=http://localhost:8888"
|
||||
})
|
||||
@Disabled
|
||||
// See https://github.com/spring-cloud/spring-cloud-app-broker/issues/315
|
||||
class DeleteInstanceWithCredHubCredentialsComponentTest extends WiremockComponentTest {
|
||||
|
||||
protected static final String APP_NAME = "first-app";
|
||||
|
||||
private static final String SERVICE_INSTANCE_ID = "instance-id";
|
||||
|
||||
@Autowired
|
||||
private OpenServiceBrokerApiFixture brokerFixture;
|
||||
|
||||
@Autowired
|
||||
private CloudControllerStubFixture cloudControllerFixture;
|
||||
|
||||
@Autowired
|
||||
private UaaStubFixture uaaFixture;
|
||||
|
||||
@Autowired
|
||||
private CredHubStubFixture credHubFixture;
|
||||
|
||||
@Test
|
||||
void deleteAppWithCredentials() {
|
||||
cloudControllerFixture.stubAppExists(APP_NAME);
|
||||
cloudControllerFixture.stubServiceBindingDoesNotExist(APP_NAME);
|
||||
cloudControllerFixture.stubDeleteApp(APP_NAME);
|
||||
|
||||
uaaFixture.stubDeleteClient("test-client");
|
||||
|
||||
credHubFixture.stubDeleteCredential(APP_NAME, SERVICE_INSTANCE_ID, "basic");
|
||||
credHubFixture.stubDeleteCredential(APP_NAME, SERVICE_INSTANCE_ID, "oauth2");
|
||||
|
||||
// when the service instance is deleted
|
||||
given(brokerFixture.serviceInstanceRequest())
|
||||
.when()
|
||||
.delete(brokerFixture.deleteServiceInstanceUrl(), SERVICE_INSTANCE_ID)
|
||||
.then()
|
||||
.statusCode(HttpStatus.ACCEPTED.value());
|
||||
|
||||
// when the "last_operation" API is polled
|
||||
given(brokerFixture.serviceInstanceRequest())
|
||||
.when()
|
||||
.get(brokerFixture.getLastInstanceOperationUrl(), SERVICE_INSTANCE_ID)
|
||||
.then()
|
||||
.statusCode(HttpStatus.OK.value())
|
||||
.body("state", is(equalTo(OperationState.IN_PROGRESS.toString())));
|
||||
|
||||
String state = brokerFixture.waitForAsyncOperationComplete(SERVICE_INSTANCE_ID);
|
||||
assertThat(state).isEqualTo(OperationState.SUCCEEDED.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.CloudControllerStubFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.CredHubStubFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.OpenServiceBrokerApiFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.UaaStubFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.WiremockServerFixture;
|
||||
@@ -39,13 +38,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
WiremockServerFixture.class,
|
||||
OpenServiceBrokerApiFixture.class,
|
||||
CloudControllerStubFixture.class,
|
||||
<<<<<<< Updated upstream
|
||||
UaaStubFixture.class,
|
||||
CredHubStubFixture.class,
|
||||
TestBindingCredentialsProviderFixture.class},
|
||||
=======
|
||||
UaaStubFixture.class},
|
||||
>>>>>>> Stashed changes
|
||||
properties = {
|
||||
"spring.cloud.appbroker.deployer.cloudfoundry.api-host=localhost",
|
||||
"spring.cloud.appbroker.deployer.cloudfoundry.api-port=8080",
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.integration.fixtures;
|
||||
|
||||
import com.github.tomakehurst.wiremock.client.MappingBuilder;
|
||||
import com.github.tomakehurst.wiremock.matching.ContentPattern;
|
||||
|
||||
import org.springframework.boot.test.context.TestComponent;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.containing;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.delete;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.get;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.noContent;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.post;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.put;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
|
||||
|
||||
@TestComponent
|
||||
public class CredHubStubFixture extends WiremockStubFixture {
|
||||
|
||||
protected CredHubStubFixture() {
|
||||
super(8888);
|
||||
}
|
||||
|
||||
public void stubWriteCredential(String credentialName, ContentPattern<?>... appMetadataPatterns) {
|
||||
MappingBuilder mappingBuilder = put(urlPathEqualTo("/api/v1/data"))
|
||||
.withRequestBody(matchingJsonPath("$.[?(@.name == '" + credentialName + "')]"))
|
||||
.withRequestBody(matchingJsonPath("$.[?(@.type == 'json')]"));
|
||||
for (ContentPattern<?> appMetadataPattern : appMetadataPatterns) {
|
||||
mappingBuilder.withRequestBody(appMetadataPattern);
|
||||
}
|
||||
stubFor(mappingBuilder
|
||||
.willReturn(ok()
|
||||
.withHeader("Content-type", "application/json")
|
||||
.withBody(credhub("put-data-json"))));
|
||||
}
|
||||
|
||||
public void stubFindCredential(String credentialName) {
|
||||
stubFor(get(urlPathEqualTo("/api/v1/data"))
|
||||
.withQueryParam("name-like", equalTo(credentialName))
|
||||
.willReturn(ok()
|
||||
.withHeader("Content-type", "application/json")
|
||||
.withBody(credhub("get-data-find"))));
|
||||
}
|
||||
|
||||
public void stubDeleteCredential(String credentialName) {
|
||||
stubFor(get(urlPathEqualTo("/api/v1/permissions"))
|
||||
.withQueryParam("credential_name", equalTo(credentialName))
|
||||
.willReturn(ok()
|
||||
.withHeader("Content-type", "application/json")
|
||||
.withBody(credhub("list-permissions"))));
|
||||
|
||||
stubFor(get(urlPathEqualTo("/api/v2/permissions"))
|
||||
.withQueryParam("path", equalTo(credentialName))
|
||||
.withQueryParam("actor", containing("uaa-user:"))
|
||||
.willReturn(ok()
|
||||
.withHeader("Content-type", "application/json")
|
||||
.withBody(credhub("get-permission"))));
|
||||
|
||||
stubFor(delete(urlPathEqualTo("/api/v2/permissions/6e9a275a-6a4b-4634-9e97-b838fd0aa2c7"))
|
||||
.willReturn(noContent()
|
||||
.withHeader("Content-type", "application/json")
|
||||
.withBody(credhub("put-data-json"))));
|
||||
}
|
||||
|
||||
public void stubDeletePermission(String credentialName) {
|
||||
stubFor(delete(urlPathEqualTo("/api/v1/data"))
|
||||
.withQueryParam("name", equalTo(credentialName))
|
||||
.willReturn(noContent()
|
||||
.withHeader("Content-type", "application/json")
|
||||
.withBody(credhub("put-data-json"))));
|
||||
}
|
||||
|
||||
public void stubAddAppPermission(String path, String actor) {
|
||||
stubFor(post(urlPathEqualTo("/api/v2/permissions"))
|
||||
.withRequestBody(matchingJsonPath("$.[?(@.path == '" + path + "')]"))
|
||||
.withRequestBody(matchingJsonPath("$.[?(@.actor == '" + actor + "')]"))
|
||||
.withRequestBody(matchingJsonPath("$.[?(@.operations[0] == 'read')]"))
|
||||
.willReturn(ok()
|
||||
.withHeader("Content-type", "application/json")
|
||||
.withBody(credhub("post-permission"))));
|
||||
}
|
||||
|
||||
public void stubGenerateUser(String appId, String serviceInstanceId,
|
||||
String descriptor, int length) {
|
||||
stubGenerate(appId, serviceInstanceId, descriptor, length, "user", "post-data-user");
|
||||
}
|
||||
|
||||
public void stubGeneratePassword(String appId, String serviceInstanceId,
|
||||
String descriptor, int length) {
|
||||
stubGenerate(appId, serviceInstanceId, descriptor, length, "password", "post-data-password");
|
||||
}
|
||||
|
||||
private void stubGenerate(String appId, String serviceInstanceId,
|
||||
String descriptor, int length,
|
||||
String type, String responseBody) {
|
||||
stubFor(post(urlPathEqualTo("/api/v1/data"))
|
||||
.withRequestBody(matchingJsonPath("$.[?(@.name == '" +
|
||||
"/" + appId +
|
||||
"/" + serviceInstanceId +
|
||||
"/" + descriptor + "')]"))
|
||||
.withRequestBody(matchingJsonPath("$.[?(@.type == '" + type + "')]"))
|
||||
.withRequestBody(matchingJsonPath("$.[?(@.parameters.length == '" + length + "')]"))
|
||||
.willReturn(ok()
|
||||
.withHeader("Content-type", "application/json")
|
||||
.withBody(credhub(responseBody))));
|
||||
}
|
||||
|
||||
public void stubDeleteCredential(String appId, String serviceInstanceId, String descriptor) {
|
||||
String credentialName = "/" + appId + "/" + serviceInstanceId + "/" + descriptor;
|
||||
stubFor(delete(urlPathEqualTo("/api/v1/data"))
|
||||
.withQueryParam("name", equalTo(credentialName))
|
||||
.willReturn(noContent()));
|
||||
}
|
||||
|
||||
public String bindingCredentialName(String brokerAppName, String serviceDefinitionId,
|
||||
String bindingId, String credentialName) {
|
||||
return "/c/" + brokerAppName + "/" + serviceDefinitionId + "/" + bindingId + "/" + credentialName;
|
||||
}
|
||||
|
||||
private String credhub(String fileRoot) {
|
||||
return readResponseFromFile(fileRoot, "credhub");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -50,8 +50,6 @@ public class WiremockServerFixture {
|
||||
|
||||
private WireMockServer ccUaaWiremockServer;
|
||||
|
||||
private WireMockServer credHubWiremockServer;
|
||||
|
||||
@PostConstruct
|
||||
public void startWiremock() {
|
||||
ccUaaWiremockServer = new WireMockServer(wireMockConfig()
|
||||
@@ -59,28 +57,20 @@ public class WiremockServerFixture {
|
||||
.usingFilesUnderClasspath("recordings"));
|
||||
ccUaaWiremockServer.start();
|
||||
|
||||
credHubWiremockServer = new WireMockServer(wireMockConfig()
|
||||
.port(8888)
|
||||
.usingFilesUnderClasspath("recordings"));
|
||||
credHubWiremockServer.start();
|
||||
|
||||
uaaFixture.stubCommonUaaRequests();
|
||||
cloudFoundryFixture.stubCommonCloudControllerRequests();
|
||||
}
|
||||
|
||||
public void stopWiremock() {
|
||||
ccUaaWiremockServer.stop();
|
||||
credHubWiremockServer.stop();
|
||||
}
|
||||
|
||||
public void resetWiremock() {
|
||||
ccUaaWiremockServer.resetAll();
|
||||
credHubWiremockServer.resetAll();
|
||||
}
|
||||
|
||||
public void verifyAllRequiredStubsUsed() {
|
||||
verifyStubs(ccUaaWiremockServer);
|
||||
verifyStubs(credHubWiremockServer);
|
||||
}
|
||||
|
||||
private void verifyStubs(WireMockServer wireMockServer) {
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"credentials": [
|
||||
{
|
||||
"version_created_at": "2017-05-09T21:09:26Z",
|
||||
"name": "/example-json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"path" : "/some-path/*",
|
||||
"operations" : [ "read", "write" ],
|
||||
"actor" : "uaa-user:106f52e2-5d01-4675-8d7a-c05ff9a2c081",
|
||||
"uuid" : "6e9a275a-6a4b-4634-9e97-b838fd0aa2c7"
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"credential_name" : "/some-credential-name",
|
||||
"permissions" : [ {
|
||||
"actor" : "uaa-user:106f52e2-5d01-4675-8d7a-c05ff9a2c081",
|
||||
"path" : "some-path",
|
||||
"operations" : [ "read" ]
|
||||
} ]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"type": "password",
|
||||
"version_created_at": "2017-01-05T01:01:01Z",
|
||||
"id": "67fc3def-bbfb-4953-83f8-4ab0682ad675",
|
||||
"name": "/example-password",
|
||||
"value": "mRPZBbAfblRpac"
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"type": "user",
|
||||
"version_created_at": "2017-01-05T01:01:01Z",
|
||||
"id": "67fc3def-bbfb-4953-83f8-4ab0682ad675",
|
||||
"name": "/example-user",
|
||||
"value": {
|
||||
"username": "FQnwWoxgSrDuqD",
|
||||
"password": "mRPZBbAfblRpac"
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"uuid": "example-uuid",
|
||||
"path": "/example-directory/*",
|
||||
"actor": "uaa-user:106f52e2-5d01-4675-8d7a-c05ff9a2c081",
|
||||
"operations": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"type": "json",
|
||||
"version_created_at": "2017-01-01T04:07:18Z",
|
||||
"id": "67fc3def-bbfb-4953-83f8-4ab0682ad675",
|
||||
"name": "/example-json",
|
||||
"value": {
|
||||
"key": 123,
|
||||
"key_list": [
|
||||
"val1",
|
||||
"val2"
|
||||
],
|
||||
"is_true": true
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
import org.springframework.boot.gradle.plugin.SpringBootPlugin
|
||||
|
||||
plugins {
|
||||
id 'org.springframework.boot' apply false
|
||||
}
|
||||
|
||||
description = "Spring Cloud App Broker Security CredHub"
|
||||
|
||||
dependencies {
|
||||
api platform(SpringBootPlugin.BOM_COORDINATES)
|
||||
api project(":spring-cloud-app-broker-core")
|
||||
api "org.springframework.credhub:spring-credhub-starter:${springCredhubVersion}"
|
||||
api "org.springframework.cloud:spring-cloud-open-service-broker-core:${openServiceBrokerVersion}"
|
||||
|
||||
testRuntimeOnly "org.junit.platform:junit-platform-launcher"
|
||||
|
||||
testImplementation "org.springframework.boot:spring-boot-starter-test"
|
||||
testImplementation "org.springframework.boot:spring-boot-starter-webflux"
|
||||
testImplementation "io.projectreactor:reactor-test"
|
||||
testImplementation "io.projectreactor.tools:blockhound-junit-platform:${blockHoundVersion}"
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.extensions.credentials;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuple2;
|
||||
import reactor.util.function.Tuples;
|
||||
|
||||
import org.springframework.credhub.core.ReactiveCredHubOperations;
|
||||
import org.springframework.credhub.support.CredentialDetails;
|
||||
import org.springframework.credhub.support.SimpleCredentialName;
|
||||
import org.springframework.credhub.support.password.PasswordCredential;
|
||||
import org.springframework.credhub.support.password.PasswordParameters;
|
||||
import org.springframework.credhub.support.password.PasswordParametersRequest;
|
||||
import org.springframework.credhub.support.user.UserCredential;
|
||||
import org.springframework.credhub.support.user.UserParametersRequest;
|
||||
|
||||
public class CredHubCredentialsGenerator implements CredentialGenerator {
|
||||
|
||||
private final ReactiveCredHubOperations credHubOperations;
|
||||
|
||||
public CredHubCredentialsGenerator(ReactiveCredHubOperations credHubOperations) {
|
||||
this.credHubOperations = credHubOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Tuple2<String, String>> generateUser(String applicationId, String serviceInstanceId, String descriptor,
|
||||
int length, boolean includeUppercaseAlpha, boolean includeLowercaseAlpha, boolean includeNumeric,
|
||||
boolean includeSpecial) {
|
||||
return credHubOperations.credentials().generate(UserParametersRequest.builder()
|
||||
.name(new SimpleCredentialName(applicationId, serviceInstanceId, descriptor))
|
||||
.parameters(passwordParameters(length, includeUppercaseAlpha, includeLowercaseAlpha, includeNumeric,
|
||||
includeSpecial))
|
||||
.build(), UserCredential.class)
|
||||
.map(CredentialDetails::getValue)
|
||||
.map(userCredential -> Tuples.of(userCredential.getUsername(), userCredential.getPassword()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<String> generateString(String applicationId, String serviceInstanceId, String descriptor, int length,
|
||||
boolean includeUppercaseAlpha, boolean includeLowercaseAlpha, boolean includeNumeric,
|
||||
boolean includeSpecial) {
|
||||
return credHubOperations.credentials()
|
||||
.generate(PasswordParametersRequest.builder()
|
||||
.name(new SimpleCredentialName(applicationId, serviceInstanceId, descriptor))
|
||||
.parameters(passwordParameters(length, includeUppercaseAlpha, includeLowercaseAlpha, includeNumeric,
|
||||
includeSpecial))
|
||||
.build(), PasswordCredential.class)
|
||||
.map(CredentialDetails::getValue)
|
||||
.map(PasswordCredential::getPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> deleteUser(String applicationId, String serviceInstanceId, String descriptor) {
|
||||
return credHubOperations.credentials()
|
||||
.deleteByName(new SimpleCredentialName(applicationId, serviceInstanceId, descriptor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> deleteString(String applicationId, String serviceInstanceId, String descriptor) {
|
||||
return credHubOperations.credentials()
|
||||
.deleteByName(new SimpleCredentialName(applicationId, serviceInstanceId, descriptor));
|
||||
}
|
||||
|
||||
private PasswordParameters passwordParameters(int length, boolean includeUppercaseAlpha,
|
||||
boolean includeLowercaseAlpha, boolean includeNumeric, boolean includeSpecial) {
|
||||
return PasswordParameters.builder()
|
||||
.length(length)
|
||||
.excludeUpper(!includeUppercaseAlpha)
|
||||
.excludeLower(!includeLowercaseAlpha)
|
||||
.excludeNumber(!includeNumeric)
|
||||
.includeSpecial(includeSpecial)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.workflow.binding;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.Logger;
|
||||
import reactor.util.Loggers;
|
||||
|
||||
import org.springframework.cloud.appbroker.service.CreateServiceInstanceAppBindingWorkflow;
|
||||
import org.springframework.cloud.servicebroker.model.binding.BindResource;
|
||||
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceAppBindingResponse;
|
||||
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceAppBindingResponse.CreateServiceInstanceAppBindingResponseBuilder;
|
||||
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingRequest;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.credhub.core.ReactiveCredHubOperations;
|
||||
import org.springframework.credhub.support.CredentialName;
|
||||
import org.springframework.credhub.support.json.JsonCredentialRequest;
|
||||
import org.springframework.credhub.support.permissions.Operation;
|
||||
import org.springframework.credhub.support.permissions.Permission;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Order(50)
|
||||
public class CredHubPersistingCreateServiceInstanceAppBindingWorkflow extends CredHubPersistingWorkflow
|
||||
implements CreateServiceInstanceAppBindingWorkflow {
|
||||
|
||||
private static final Logger LOG = Loggers.getLogger(CredHubPersistingCreateServiceInstanceAppBindingWorkflow.class);
|
||||
|
||||
private static final String CREDHUB_REF_KEY = "credhub-ref";
|
||||
|
||||
private static final String CREDENTIAL_CLIENT_ID = "credential_client_id";
|
||||
|
||||
private final ReactiveCredHubOperations credHubOperations;
|
||||
|
||||
public CredHubPersistingCreateServiceInstanceAppBindingWorkflow(ReactiveCredHubOperations credHubOperations,
|
||||
String appName) {
|
||||
super(appName);
|
||||
this.credHubOperations = credHubOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<CreateServiceInstanceAppBindingResponseBuilder> buildResponse(
|
||||
CreateServiceInstanceBindingRequest request, CreateServiceInstanceAppBindingResponseBuilder responseBuilder) {
|
||||
return Mono.just(responseBuilder.build())
|
||||
.flatMap(response -> {
|
||||
if (!CollectionUtils.isEmpty(response.getCredentials())) {
|
||||
return buildCredentialName(request.getServiceDefinitionId(), request.getBindingId())
|
||||
.flatMap(credentialName -> persistBindingCredentials(request, response, credentialName)
|
||||
.doOnRequest(l -> LOG.debug("Storing binding credentials with name '{}' in CredHub",
|
||||
credentialName.getName()))
|
||||
.doOnSuccess(r -> LOG
|
||||
.debug("Finished storing binding credentials with name '{}' in CredHub",
|
||||
credentialName.getName()))
|
||||
.doOnError(exception -> LOG.error(String
|
||||
.format("Error storing binding credentials with name '%s' in CredHub with error: '%s'",
|
||||
credentialName.getName(), exception.getMessage()), exception)));
|
||||
}
|
||||
return Mono.just(responseBuilder);
|
||||
});
|
||||
}
|
||||
|
||||
private Mono<CreateServiceInstanceAppBindingResponseBuilder> persistBindingCredentials(
|
||||
CreateServiceInstanceBindingRequest request, CreateServiceInstanceAppBindingResponse response,
|
||||
CredentialName credentialName) {
|
||||
return writeCredential(response, credentialName)
|
||||
.then(writePermissions(request, credentialName))
|
||||
.thenReturn(buildReplacementBindingResponse(response, credentialName));
|
||||
}
|
||||
|
||||
private Mono<Void> writeCredential(CreateServiceInstanceAppBindingResponse response,
|
||||
CredentialName credentialName) {
|
||||
return credHubOperations.credentials()
|
||||
.write(JsonCredentialRequest.builder()
|
||||
.name(credentialName)
|
||||
.value(response.getCredentials())
|
||||
.build())
|
||||
.then();
|
||||
}
|
||||
|
||||
private Mono<Void> writePermissions(CreateServiceInstanceBindingRequest request,
|
||||
CredentialName credentialName) {
|
||||
BindResource bindResource = request.getBindResource();
|
||||
return Mono.defer(() -> {
|
||||
if (bindResource.getAppGuid() != null) {
|
||||
return credHubOperations.permissionsV2()
|
||||
.addPermissions(credentialName, Permission.builder()
|
||||
.app(bindResource.getAppGuid())
|
||||
.operation(Operation.READ)
|
||||
.build())
|
||||
.then();
|
||||
}
|
||||
if (bindResource.getProperty(CREDENTIAL_CLIENT_ID) != null) {
|
||||
return credHubOperations.permissionsV2()
|
||||
.addPermissions(credentialName, Permission.builder()
|
||||
.client(bindResource.getProperty(CREDENTIAL_CLIENT_ID).toString())
|
||||
.operation(Operation.READ)
|
||||
.build())
|
||||
.then();
|
||||
}
|
||||
return Mono.empty();
|
||||
});
|
||||
}
|
||||
|
||||
private CreateServiceInstanceAppBindingResponseBuilder buildReplacementBindingResponse(
|
||||
CreateServiceInstanceAppBindingResponse response, CredentialName credentialName) {
|
||||
return CreateServiceInstanceAppBindingResponse.builder()
|
||||
.async(response.isAsync())
|
||||
.bindingExisted(response.isBindingExisted())
|
||||
.credentials(CREDHUB_REF_KEY, credentialName.getName())
|
||||
.operation(response.getOperation())
|
||||
.syslogDrainUrl(response.getSyslogDrainUrl())
|
||||
.volumeMounts(response.getVolumeMounts());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.workflow.binding;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.Logger;
|
||||
import reactor.util.Loggers;
|
||||
|
||||
import org.springframework.cloud.appbroker.service.DeleteServiceInstanceBindingWorkflow;
|
||||
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingRequest;
|
||||
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingResponse.DeleteServiceInstanceBindingResponseBuilder;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.credhub.core.ReactiveCredHubOperations;
|
||||
import org.springframework.credhub.support.CredentialName;
|
||||
import org.springframework.credhub.support.ServiceInstanceCredentialName;
|
||||
|
||||
@Order(50)
|
||||
public class CredHubPersistingDeleteServiceInstanceBindingWorkflow extends CredHubPersistingWorkflow
|
||||
implements DeleteServiceInstanceBindingWorkflow {
|
||||
|
||||
private static final Logger LOG = Loggers.getLogger(CredHubPersistingDeleteServiceInstanceBindingWorkflow.class);
|
||||
|
||||
private final ReactiveCredHubOperations credHubOperations;
|
||||
|
||||
public CredHubPersistingDeleteServiceInstanceBindingWorkflow(ReactiveCredHubOperations credHubOperations,
|
||||
String appName) {
|
||||
super(appName);
|
||||
this.credHubOperations = credHubOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<DeleteServiceInstanceBindingResponseBuilder> buildResponse(DeleteServiceInstanceBindingRequest request,
|
||||
DeleteServiceInstanceBindingResponseBuilder responseBuilder) {
|
||||
return buildCredentialName(request.getServiceDefinitionId(), request.getBindingId())
|
||||
.filterWhen(this::credentialExists)
|
||||
.delayUntil(this::deletePermission)
|
||||
.delayUntil(this::deleteCredential)
|
||||
.thenReturn(responseBuilder);
|
||||
}
|
||||
|
||||
private Mono<Void> deleteCredential(ServiceInstanceCredentialName credentialName) {
|
||||
return credHubOperations.credentials()
|
||||
.deleteByName(credentialName)
|
||||
.doOnRequest(
|
||||
l -> LOG.debug("Deleting binding credentials with name '{}' in CredHub", credentialName.getName()))
|
||||
.doOnSuccess(r -> LOG
|
||||
.debug("Finished deleting binding credentials with name '{}' in CredHub", credentialName.getName()))
|
||||
.doOnError(exception -> LOG.error(
|
||||
String.format("Error deleting binding credentials with name '%s' in CredHub with error: '%s'",
|
||||
credentialName.getName(), exception.getMessage()), exception));
|
||||
}
|
||||
|
||||
private Mono<Void> deletePermission(ServiceInstanceCredentialName credentialName) {
|
||||
return credHubOperations.permissions()
|
||||
.getPermissions(credentialName)
|
||||
.flatMap(permission -> credHubOperations.permissionsV2()
|
||||
.getPermissionsByPathAndActor(credentialName, permission.getActor()))
|
||||
.flatMap(credentialPermission -> credHubOperations.permissionsV2()
|
||||
.deletePermission(credentialPermission.getId())
|
||||
.doOnRequest(
|
||||
l -> LOG.debug("Deleting binding permission for credential with name '{}' in CredHub",
|
||||
credentialName.getName()))
|
||||
.doOnSuccess(r -> LOG
|
||||
.debug("Finished deleting binding permission for credential with name '{}' in CredHub",
|
||||
credentialName.getName()))
|
||||
.doOnError(exception -> LOG.error(
|
||||
String.format(
|
||||
"Error deleting binding permission for credential with name '%s' in CredHub with error: '%s'",
|
||||
credentialName.getName(), exception.getMessage()), exception)))
|
||||
.then();
|
||||
}
|
||||
|
||||
private Mono<Boolean> credentialExists(CredentialName credentialName) {
|
||||
return credHubOperations.credentials()
|
||||
.findByName(credentialName)
|
||||
.collectList()
|
||||
.map(credentialSummaries -> !credentialSummaries.isEmpty());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.workflow.binding;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.credhub.support.ServiceInstanceCredentialName;
|
||||
|
||||
public class CredHubPersistingWorkflow {
|
||||
|
||||
private static final String CREDENTIALS_NAME = "credentials-json";
|
||||
|
||||
private final String appName;
|
||||
|
||||
protected CredHubPersistingWorkflow(String appName) {
|
||||
this.appName = appName;
|
||||
}
|
||||
|
||||
protected Mono<ServiceInstanceCredentialName> buildCredentialName(String serviceDefinitionId, String bindingId) {
|
||||
return Mono.just(ServiceInstanceCredentialName.builder()
|
||||
.serviceBrokerName(this.appName)
|
||||
.serviceOfferingName(serviceDefinitionId)
|
||||
.serviceBindingId(bindingId)
|
||||
.credentialName(CREDENTIALS_NAME)
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.extensions.credentials;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.credhub.core.ReactiveCredHubOperations;
|
||||
import org.springframework.credhub.core.credential.ReactiveCredHubCredentialOperations;
|
||||
import org.springframework.credhub.support.CredentialDetails;
|
||||
import org.springframework.credhub.support.CredentialType;
|
||||
import org.springframework.credhub.support.SimpleCredentialName;
|
||||
import org.springframework.credhub.support.password.PasswordCredential;
|
||||
import org.springframework.credhub.support.password.PasswordParameters;
|
||||
import org.springframework.credhub.support.user.UserCredential;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CredHubCredentialsGeneratorTest {
|
||||
|
||||
@Mock
|
||||
private ReactiveCredHubOperations credHubOperations;
|
||||
|
||||
@Mock
|
||||
private ReactiveCredHubCredentialOperations credHubCredentialOperations;
|
||||
|
||||
private CredHubCredentialsGenerator generator;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.generator = new CredHubCredentialsGenerator(credHubOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
void passwordParameters() {
|
||||
PasswordParameters params = ReflectionTestUtils
|
||||
.invokeMethod(generator, "passwordParameters", 42, false, false, false, false);
|
||||
assertThat(params.getLength()).isEqualTo(42);
|
||||
assertThat(params.getExcludeUpper()).isTrue();
|
||||
assertThat(params.getExcludeLower()).isTrue();
|
||||
assertThat(params.getExcludeNumber()).isTrue();
|
||||
assertThat(params.getIncludeSpecial()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateUser() {
|
||||
given(this.credHubOperations.credentials())
|
||||
.willReturn(credHubCredentialOperations);
|
||||
|
||||
CredentialDetails<UserCredential> creds = new CredentialDetails<>("id",
|
||||
new SimpleCredentialName("app-service"), CredentialType.PASSWORD,
|
||||
new UserCredential("username", "password"));
|
||||
|
||||
given(this.credHubCredentialOperations.generate(any(), eq(UserCredential.class)))
|
||||
.willReturn(Mono.just(creds));
|
||||
|
||||
StepVerifier.create(generator.generateUser("foo", "bar", "hello", 12, false, false, false, false))
|
||||
.assertNext(tuple2 -> {
|
||||
assertThat(tuple2.getT1()).isEqualTo("username");
|
||||
assertThat(tuple2.getT2()).isEqualTo("password");
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateString() {
|
||||
given(this.credHubOperations.credentials())
|
||||
.willReturn(credHubCredentialOperations);
|
||||
|
||||
CredentialDetails<PasswordCredential> creds = new CredentialDetails<>("id",
|
||||
new SimpleCredentialName("app-service"), CredentialType.PASSWORD,
|
||||
new PasswordCredential("password"));
|
||||
|
||||
given(this.credHubCredentialOperations.generate(any(), eq(PasswordCredential.class)))
|
||||
.willReturn(Mono.just(creds));
|
||||
|
||||
StepVerifier.create(generator.generateString("foo", "bar", "hello", 12, false, false, false, false))
|
||||
.assertNext(password -> assertThat(password).isEqualTo("password"))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteUser() {
|
||||
given(this.credHubOperations.credentials())
|
||||
.willReturn(credHubCredentialOperations);
|
||||
|
||||
given(this.credHubCredentialOperations.deleteByName(any()))
|
||||
.willReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(generator.deleteUser("foo", "bar", "hello"))
|
||||
.verifyComplete();
|
||||
|
||||
verify(credHubCredentialOperations).deleteByName(new SimpleCredentialName("foo", "bar", "hello"));
|
||||
verifyNoMoreInteractions(credHubOperations);
|
||||
verifyNoMoreInteractions(credHubCredentialOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteString() {
|
||||
given(this.credHubOperations.credentials())
|
||||
.willReturn(credHubCredentialOperations);
|
||||
|
||||
given(this.credHubCredentialOperations.deleteByName(any()))
|
||||
.willReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(generator.deleteString("foo", "bar", "hello"))
|
||||
.verifyComplete();
|
||||
|
||||
verify(credHubCredentialOperations).deleteByName(new SimpleCredentialName("foo", "bar", "hello"));
|
||||
verifyNoMoreInteractions(credHubOperations);
|
||||
verifyNoMoreInteractions(credHubCredentialOperations);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.workflow.binding;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.cloud.servicebroker.model.binding.BindResource;
|
||||
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceAppBindingResponse;
|
||||
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceAppBindingResponse.CreateServiceInstanceAppBindingResponseBuilder;
|
||||
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingRequest;
|
||||
import org.springframework.cloud.servicebroker.model.binding.VolumeMount;
|
||||
import org.springframework.credhub.core.ReactiveCredHubOperations;
|
||||
import org.springframework.credhub.core.credential.ReactiveCredHubCredentialOperations;
|
||||
import org.springframework.credhub.core.permissionV2.ReactiveCredHubPermissionV2Operations;
|
||||
import org.springframework.credhub.support.CredentialDetails;
|
||||
import org.springframework.credhub.support.CredentialName;
|
||||
import org.springframework.credhub.support.CredentialPermission;
|
||||
import org.springframework.credhub.support.ServiceInstanceCredentialName;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CredHubPersistingCreateServiceInstanceAppBindingWorkflowTest {
|
||||
|
||||
@Mock
|
||||
private ReactiveCredHubOperations credHubOperations;
|
||||
|
||||
@Mock
|
||||
private ReactiveCredHubCredentialOperations credHubCredentialOperations;
|
||||
|
||||
@Mock
|
||||
private ReactiveCredHubPermissionV2Operations credHubPermissionOperations;
|
||||
|
||||
private CredHubPersistingCreateServiceInstanceAppBindingWorkflow workflow;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.workflow = new CredHubPersistingCreateServiceInstanceAppBindingWorkflow(credHubOperations,
|
||||
"test-app-name");
|
||||
}
|
||||
|
||||
@Test
|
||||
void noBindingCredentials() {
|
||||
CreateServiceInstanceBindingRequest request = CreateServiceInstanceBindingRequest
|
||||
.builder()
|
||||
.bindingId("foo-binding-id")
|
||||
.serviceInstanceId("foo-instance-id")
|
||||
.serviceDefinitionId("foo-definition-id")
|
||||
.build();
|
||||
|
||||
CreateServiceInstanceAppBindingResponseBuilder responseBuilder = CreateServiceInstanceAppBindingResponse
|
||||
.builder()
|
||||
.bindingExisted(true)
|
||||
.syslogDrainUrl("https://logs.example.local")
|
||||
.volumeMounts(VolumeMount.builder().build())
|
||||
.volumeMounts(VolumeMount.builder().build())
|
||||
.volumeMounts(Arrays.asList(
|
||||
VolumeMount.builder().build(),
|
||||
VolumeMount.builder().build()
|
||||
));
|
||||
|
||||
StepVerifier
|
||||
.create(this.workflow.buildResponse(request, responseBuilder))
|
||||
.assertNext(createServiceInstanceAppBindingResponseBuilder -> {
|
||||
CreateServiceInstanceAppBindingResponse response = createServiceInstanceAppBindingResponseBuilder
|
||||
.build();
|
||||
assertThat(response.isBindingExisted()).isEqualTo(true);
|
||||
assertThat(response.getCredentials()).hasSize(0);
|
||||
assertThat(response.getSyslogDrainUrl()).isEqualTo("https://logs.example.local");
|
||||
assertThat(response.getVolumeMounts()).hasSize(4);
|
||||
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
verifyNoInteractions(this.credHubCredentialOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("serial")
|
||||
void storeCredentialsInCredHub() {
|
||||
CredentialName credentialName = ServiceInstanceCredentialName.builder()
|
||||
.serviceBrokerName("test-app-name")
|
||||
.serviceOfferingName("foo-definition-id")
|
||||
.serviceBindingId("foo-binding-id")
|
||||
.credentialName("credentials-json")
|
||||
.build();
|
||||
|
||||
CreateServiceInstanceBindingRequest request = CreateServiceInstanceBindingRequest
|
||||
.builder()
|
||||
.bindingId("foo-binding-id")
|
||||
.serviceInstanceId("foo-instance-id")
|
||||
.serviceDefinitionId("foo-definition-id")
|
||||
.bindResource(BindResource.builder()
|
||||
.appGuid("app-id")
|
||||
.properties("credential_client_id", "client-id")
|
||||
.build())
|
||||
.build();
|
||||
|
||||
Map<String, Object> credentials = new HashMap<String, Object>() {{
|
||||
put("credential4", "value4");
|
||||
put("credential5", "value5");
|
||||
}};
|
||||
|
||||
CreateServiceInstanceAppBindingResponseBuilder responseBuilder = CreateServiceInstanceAppBindingResponse
|
||||
.builder()
|
||||
.bindingExisted(true)
|
||||
.credentials("credential1", "value1")
|
||||
.credentials("credential2", 2)
|
||||
.credentials("credential3", true)
|
||||
.credentials(credentials)
|
||||
.syslogDrainUrl("https://logs.example.local")
|
||||
.volumeMounts(VolumeMount.builder().build())
|
||||
.volumeMounts(VolumeMount.builder().build())
|
||||
.volumeMounts(Arrays.asList(
|
||||
VolumeMount.builder().build(),
|
||||
VolumeMount.builder().build()
|
||||
));
|
||||
|
||||
given(this.credHubOperations.credentials())
|
||||
.willReturn(credHubCredentialOperations);
|
||||
given(this.credHubOperations.permissionsV2())
|
||||
.willReturn(credHubPermissionOperations);
|
||||
|
||||
given(this.credHubCredentialOperations.write(any()))
|
||||
.willReturn(Mono.just(new CredentialDetails<>()));
|
||||
|
||||
given(this.credHubPermissionOperations.addPermissions(any(), any()))
|
||||
.willReturn(Mono.just(Mockito.mock(CredentialPermission.class)));
|
||||
|
||||
StepVerifier
|
||||
.create(this.workflow.buildResponse(request, responseBuilder))
|
||||
.assertNext(createServiceInstanceAppBindingResponseBuilder -> {
|
||||
CreateServiceInstanceAppBindingResponse response = createServiceInstanceAppBindingResponseBuilder
|
||||
.build();
|
||||
assertThat(response.isBindingExisted()).isEqualTo(true);
|
||||
assertThat(response.getCredentials()).hasSize(1);
|
||||
assertThat(response.getCredentials().get("credhub-ref")).isEqualTo(credentialName.getName());
|
||||
assertThat(response.getSyslogDrainUrl()).isEqualTo("https://logs.example.local");
|
||||
assertThat(response.getVolumeMounts()).hasSize(4);
|
||||
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
verify(this.credHubCredentialOperations, times(1))
|
||||
.write(any());
|
||||
verify(this.credHubPermissionOperations, times(1))
|
||||
.addPermissions(any(), any());
|
||||
verifyNoMoreInteractions(this.credHubCredentialOperations);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cloud.appbroker.workflow.binding;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingRequest;
|
||||
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingResponse;
|
||||
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingResponse.DeleteServiceInstanceBindingResponseBuilder;
|
||||
import org.springframework.credhub.core.ReactiveCredHubOperations;
|
||||
import org.springframework.credhub.core.credential.ReactiveCredHubCredentialOperations;
|
||||
import org.springframework.credhub.core.permission.ReactiveCredHubPermissionOperations;
|
||||
import org.springframework.credhub.core.permissionV2.ReactiveCredHubPermissionV2Operations;
|
||||
import org.springframework.credhub.support.CredentialName;
|
||||
import org.springframework.credhub.support.CredentialPermission;
|
||||
import org.springframework.credhub.support.CredentialSummary;
|
||||
import org.springframework.credhub.support.ServiceInstanceCredentialName;
|
||||
import org.springframework.credhub.support.permissions.Actor;
|
||||
import org.springframework.credhub.support.permissions.Operation;
|
||||
import org.springframework.credhub.support.permissions.Permission;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CredHubPersistingDeleteServiceInstanceBindingWorkflowTest {
|
||||
|
||||
@Mock
|
||||
private ReactiveCredHubOperations credHubOperations;
|
||||
|
||||
@Mock
|
||||
private ReactiveCredHubCredentialOperations credHubCredentialOperations;
|
||||
|
||||
@Mock
|
||||
private ReactiveCredHubPermissionV2Operations credHubPermissionV2Operations;
|
||||
|
||||
@Mock
|
||||
private ReactiveCredHubPermissionOperations credHubPermissionOperations;
|
||||
|
||||
private CredHubPersistingDeleteServiceInstanceBindingWorkflow workflow;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.workflow = new CredHubPersistingDeleteServiceInstanceBindingWorkflow(credHubOperations, "test-app-name");
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteCredentialsFromCredHubWhenFound() {
|
||||
CredentialName credentialName = ServiceInstanceCredentialName.builder()
|
||||
.serviceBrokerName("test-app-name")
|
||||
.serviceOfferingName("foo-definition-id")
|
||||
.serviceBindingId("foo-binding-id")
|
||||
.credentialName("credentials-json")
|
||||
.build();
|
||||
|
||||
DeleteServiceInstanceBindingRequest request = DeleteServiceInstanceBindingRequest
|
||||
.builder()
|
||||
.bindingId("foo-binding-id")
|
||||
.serviceInstanceId("foo-instance-id")
|
||||
.serviceDefinitionId("foo-definition-id")
|
||||
.build();
|
||||
|
||||
DeleteServiceInstanceBindingResponseBuilder responseBuilder =
|
||||
DeleteServiceInstanceBindingResponse.builder();
|
||||
|
||||
given(this.credHubOperations.credentials())
|
||||
.willReturn(credHubCredentialOperations);
|
||||
|
||||
given(this.credHubOperations.permissionsV2())
|
||||
.willReturn(credHubPermissionV2Operations);
|
||||
|
||||
given(this.credHubOperations.permissions())
|
||||
.willReturn(credHubPermissionOperations);
|
||||
|
||||
given(this.credHubCredentialOperations.findByName(credentialName))
|
||||
.willReturn(Flux.fromIterable(Collections.singletonList(new CredentialSummary(credentialName))));
|
||||
|
||||
CredentialPermission credentialPermission = new CredentialPermission(credentialName,
|
||||
Permission.builder().app("app-id").operation(Operation.READ).build());
|
||||
ReflectionTestUtils.setField(credentialPermission, "uuid", "permission-uuid");
|
||||
|
||||
given(this.credHubPermissionV2Operations.getPermissionsByPathAndActor(any(), any()))
|
||||
.willReturn(Mono.just(credentialPermission));
|
||||
|
||||
given(this.credHubPermissionV2Operations.deletePermission("permission-uuid"))
|
||||
.willReturn(Mono.empty());
|
||||
|
||||
Permission permission = Permission.builder().operation(Operation.READ).client("client-id").build();
|
||||
given(this.credHubPermissionOperations.getPermissions(any()))
|
||||
.willReturn(Flux.just(permission));
|
||||
|
||||
given(this.credHubCredentialOperations.deleteByName(any()))
|
||||
.willReturn(Mono.empty());
|
||||
|
||||
StepVerifier
|
||||
.create(this.workflow.buildResponse(request, responseBuilder))
|
||||
.expectNext(responseBuilder)
|
||||
.verifyComplete();
|
||||
|
||||
verify(this.credHubCredentialOperations, times(1))
|
||||
.deleteByName(eq(credentialName));
|
||||
verify(this.credHubPermissionV2Operations, times(1))
|
||||
.getPermissionsByPathAndActor(eq(credentialName), eq(Actor.client("client-id")));
|
||||
verify(this.credHubPermissionV2Operations, times(1))
|
||||
.deletePermission(eq("permission-uuid"));
|
||||
|
||||
verifyNoMoreInteractions(this.credHubCredentialOperations);
|
||||
verifyNoMoreInteractions(this.credHubPermissionOperations);
|
||||
verifyNoMoreInteractions(this.credHubPermissionV2Operations);
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteCredentialsFromCredHubWhenNotFound() {
|
||||
DeleteServiceInstanceBindingRequest request = DeleteServiceInstanceBindingRequest
|
||||
.builder()
|
||||
.bindingId("foo-binding-id")
|
||||
.serviceInstanceId("foo-instance-id")
|
||||
.serviceDefinitionId("foo-definition-id")
|
||||
.build();
|
||||
|
||||
DeleteServiceInstanceBindingResponseBuilder responseBuilder =
|
||||
DeleteServiceInstanceBindingResponse.builder();
|
||||
|
||||
given(this.credHubOperations.credentials())
|
||||
.willReturn(credHubCredentialOperations);
|
||||
|
||||
given(this.credHubCredentialOperations.findByName(any()))
|
||||
.willReturn(Flux.fromIterable(Collections.emptyList()));
|
||||
|
||||
StepVerifier
|
||||
.create(this.workflow.buildResponse(request, responseBuilder))
|
||||
.expectNext(responseBuilder)
|
||||
.verifyComplete();
|
||||
|
||||
verifyNoMoreInteractions(this.credHubCredentialOperations);
|
||||
verifyNoMoreInteractions(this.credHubPermissionOperations);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,7 +19,6 @@ description = "Spring Cloud App Broker Starter for Cloud Foundry"
|
||||
dependencies {
|
||||
api project(":spring-cloud-starter-app-broker")
|
||||
api project(":spring-cloud-app-broker-deployer-cloudfoundry")
|
||||
api project(":spring-cloud-app-broker-security-credhub")
|
||||
api "org.cloudfoundry:cloudfoundry-client-reactor:${cfJavaClientVersion}"
|
||||
api "org.cloudfoundry:cloudfoundry-operations:${cfJavaClientVersion}"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user