Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Poc secrets #9539

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@
<groupId>io.gravitee.node</groupId>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Aqua detected vulnerability in your code

Vulnerability ID: CVE-2024-38820
Check Name: The fix for CVE-2022-22968 made disallowedFieldspatterns in DataBinder ...
Severity: MEDIUM
Fixed Version: 6.1.14, 6.0.25, 5.3.41, 6.2.0-RC2
Reachable Path(s) Found: No
Description: The fix for CVE-2022-22968 made disallowedFields patterns in DataBinder case insensitive. However, String.toLowerCase() has some Locale dependent exceptions that could potentially result in fields not protected as expected.
[This comment was created by Aqua Pipeline]

Read more at https://avd.aquasec.com/nvd/cve-2024-38820

<artifactId>gravitee-node-vertx</artifactId>
</dependency>
<dependency>
<groupId>io.gravitee.apim.definition</groupId>
<artifactId>gravitee-apim-definition-jackson</artifactId>
<version>4.5.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package io.gravitee.definition.model.services.secrets;

import static io.gravitee.node.api.secrets.runtime.discovery.PayloadLocation.PLUGIN_KIND;

import io.gravitee.definition.model.v4.Api;
import io.gravitee.definition.model.v4.endpointgroup.service.EndpointGroupServices;
import io.gravitee.definition.model.v4.endpointgroup.service.EndpointServices;
import io.gravitee.definition.model.v4.flow.Flow;
import io.gravitee.definition.model.v4.plan.PlanSecurity;
import io.gravitee.definition.model.v4.service.Service;
import io.gravitee.node.api.secrets.runtime.discovery.Definition;
import io.gravitee.node.api.secrets.runtime.discovery.DefinitionBrowser;
import io.gravitee.node.api.secrets.runtime.discovery.DefinitionPayloadNotifier;
import io.gravitee.node.api.secrets.runtime.discovery.PayloadLocation;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* @author Benoit BORDIGONI (benoit.bordigoni at graviteesource.com)
* @author GraviteeSource Team
*/
public class ApiV4DefinitionBrowser implements DefinitionBrowser<Api> {

@Override
public boolean canHandle(Object definition) {
return definition != null && Objects.equals(definition.getClass(), Api.class);
}

@Override
public Definition getDefinitionLocation(Api definition, Map<String, String> metadata) {
return new Definition("api-v4", metadata.get("api_cross_id"), Optional.ofNullable(metadata.get("deployment_number")));
}

@Override
public void findPayloads(Api definition, DefinitionPayloadNotifier notifier) {
// listeners
definition
.getListeners()
.stream()
.flatMap(l -> l.getEntrypoints().stream())
.forEach(entrypoint -> {
String payload = entrypoint.getConfiguration();
notifier.onPayload(payload, new PayloadLocation(PLUGIN_KIND, entrypoint.getType()), entrypoint::setConfiguration);
});

// resources
definition
.getResources()
.forEach(resource -> {
String payload = resource.getConfiguration();
notifier.onPayload(payload, new PayloadLocation(PLUGIN_KIND, resource.getType()), resource::setConfiguration);
});

// flows api and plan
List<Flow> flows = definition
.getPlans()
.stream()
.flatMap(p -> p.getFlows().stream())
.collect(Collectors.toCollection(ArrayList::new));
flows.addAll(definition.getFlows());
Stream
.concat(
Stream.concat(
flows.stream().flatMap(flow -> flow.getRequest().stream()),
flows.stream().flatMap(flow -> flow.getResponse().stream())
),
Stream.concat(
flows.stream().flatMap(flow -> flow.getPublish().stream()),
flows.stream().flatMap(flow -> flow.getSubscribe().stream())
)
)
.forEach(step -> {
var payload = step.getConfiguration();
notifier.onPayload(payload, new PayloadLocation(PLUGIN_KIND, step.getPolicy()), step::setConfiguration);
});

definition
.getPlans()
.forEach(plan -> {
PlanSecurity security = plan.getSecurity();
String payload = security.getConfiguration();
notifier.onPayload(payload, new PayloadLocation(PLUGIN_KIND, security.getType()), security::setConfiguration);
});

// endpoint groups
definition
.getEndpointGroups()
.stream()
.flatMap(endpointGroup -> {
EndpointGroupServices services = endpointGroup.getServices();
Stream
.of(services.getDiscovery(), services.getHealthCheck())
.filter(Service::isEnabled)
.forEach(service -> {
String payload = service.getConfiguration();
notifier.onPayload(payload, new PayloadLocation(PLUGIN_KIND, service.getType()), service::setConfiguration);
});
String payload = endpointGroup.getSharedConfiguration();
notifier.onPayload(
payload,
new PayloadLocation(PLUGIN_KIND, endpointGroup.getType()),
endpointGroup::setSharedConfiguration
);
return endpointGroup.getEndpoints().stream();
})
.forEach(endpoint -> {
EndpointServices services = endpoint.getServices();
Stream
.of(services.getHealthCheck())
.filter(Service::isEnabled)
.forEach(service -> {
String payload = service.getConfiguration();
notifier.onPayload(payload, new PayloadLocation(PLUGIN_KIND, service.getType()), service::setConfiguration);
});
String payload = endpoint.getConfiguration();
notifier.onPayload(payload, new PayloadLocation(PLUGIN_KIND, endpoint.getType()), endpoint::setConfiguration);
payload = endpoint.getSharedConfigurationOverride();
notifier.onPayload(payload, new PayloadLocation(PLUGIN_KIND, endpoint.getType()), endpoint::setSharedConfigurationOverride);
});

// services
Service dynamicProperty = definition.getServices().getDynamicProperty();
String payload = dynamicProperty.getConfiguration();
notifier.onPayload(payload, new PayloadLocation(PLUGIN_KIND, dynamicProperty.getType()), dynamicProperty::setConfiguration);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@
<artifactId>gravitee-node-api</artifactId>
</dependency>

<dependency>
<groupId>io.gravitee.node</groupId>
<artifactId>gravitee-node-secrets-runtime</artifactId>
<version>${gravitee-node.version}</version>
</dependency>

<dependency>
<groupId>io.gravitee.apim.definition</groupId>
<artifactId>gravitee-apim-definition-jackson</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.gravitee.gateway.handlers.api.manager.impl;

import com.graviteesource.services.runtimesecrets.RuntimeSecretsService;
import io.gravitee.common.event.EventManager;
import io.gravitee.common.util.DataEncryptor;
import io.gravitee.definition.model.DefinitionVersion;
Expand All @@ -29,7 +30,6 @@
import io.gravitee.gateway.reactor.ReactorEvent;
import io.gravitee.node.api.license.ForbiddenFeatureException;
import io.gravitee.node.api.license.InvalidLicenseException;
import io.gravitee.node.api.license.License;
import io.gravitee.node.api.license.LicenseManager;
import java.util.Collection;
import java.util.List;
Expand Down Expand Up @@ -60,16 +60,19 @@ public class ApiManagerImpl implements ApiManager {
private final LicenseManager licenseManager;
private final Map<String, ReactableApi<?>> apis = new ConcurrentHashMap<>();
private final Map<Class<? extends ReactableApi<?>>, ? extends Deployer<?>> deployers;
private final RuntimeSecretsService runtimeSecretsService;

public ApiManagerImpl(
final EventManager eventManager,
final GatewayConfiguration gatewayConfiguration,
LicenseManager licenseManager,
final DataEncryptor dataEncryptor
final DataEncryptor dataEncryptor,
final RuntimeSecretsService runtimeSecretsService
) {
this.eventManager = eventManager;
this.gatewayConfiguration = gatewayConfiguration;
this.licenseManager = licenseManager;
this.runtimeSecretsService = runtimeSecretsService;
deployers =
Map.of(
Api.class,
Expand Down Expand Up @@ -210,6 +213,9 @@ private void deploy(ReactableApi api) {
}

apis.put(api.getId(), api);

runtimeSecretsService.onDefinitionDeploy(api.getEnvironmentId(), api.getDefinition(), api.getDeploymentProperties());

eventManager.publishEvent(ReactorEvent.DEPLOY, api);
log.info("{} has been deployed", api);
} else {
Expand Down Expand Up @@ -250,6 +256,9 @@ private void update(ReactableApi<?> api) {
}

apis.put(api.getId(), api);

runtimeSecretsService.onDefinitionDeploy(api.getEnvironmentId(), api.getDefinition(), api.getDeploymentProperties());

eventManager.publishEvent(ReactorEvent.UPDATE, api);
log.info("{} has been updated", api);
} else {
Expand All @@ -265,6 +274,11 @@ private void undeploy(String apiId) {
if (currentApi != null) {
MDC.put("api", apiId);
log.debug("Undeployment of {}", currentApi);
runtimeSecretsService.onDefinitionUnDeploy(
currentApi.getEnvironmentId(),
currentApi.getDefinition(),
currentApi.getDeploymentProperties()
);

eventManager.publishEvent(ReactorEvent.UNDEPLOY, currentApi);
log.info("{} has been undeployed", currentApi);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.gravitee.gateway.handlers.api.spring;

import com.graviteesource.services.runtimesecrets.RuntimeSecretsService;
import io.gravitee.common.event.EventManager;
import io.gravitee.common.util.DataEncryptor;
import io.gravitee.gateway.core.classloader.DefaultClassLoader;
Expand Down Expand Up @@ -88,9 +89,10 @@ public ApiManager apiManager(
EventManager eventManager,
GatewayConfiguration gatewayConfiguration,
LicenseManager licenseManager,
RuntimeSecretsService runtimeSecretsService,
DataEncryptor dataEncryptor
) {
return new ApiManagerImpl(eventManager, gatewayConfiguration, licenseManager, dataEncryptor);
return new ApiManagerImpl(eventManager, gatewayConfiguration, licenseManager, dataEncryptor, runtimeSecretsService);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,17 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyCollection;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.graviteesource.services.runtimesecrets.RuntimeSecretsService;
import io.gravitee.common.event.EventManager;
import io.gravitee.common.util.DataEncryptor;
import io.gravitee.definition.model.Plan;
Expand Down Expand Up @@ -79,11 +86,14 @@ public class ApiManagerTest {
@Mock
private LicenseManager licenseManager;

@Mock
RuntimeSecretsService runtimeSecretsService;

private ApiManagerImpl apiManager;

@Before
public void setUp() throws Exception {
apiManager = spy(new ApiManagerImpl(eventManager, gatewayConfiguration, licenseManager, dataEncryptor));
apiManager = spy(new ApiManagerImpl(eventManager, gatewayConfiguration, licenseManager, dataEncryptor, runtimeSecretsService));
when(gatewayConfiguration.shardingTags()).thenReturn(Optional.empty());
when(gatewayConfiguration.hasMatchingTags(any())).thenCallRealMethod();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,18 @@
import static java.util.Collections.singletonList;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyCollection;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.graviteesource.services.runtimesecrets.RuntimeSecretsService;
import io.gravitee.common.event.EventManager;
import io.gravitee.common.util.DataEncryptor;
import io.gravitee.definition.model.v4.listener.Listener;
Expand Down Expand Up @@ -77,9 +86,12 @@ public class ApiManagerV4Test {
@Mock
private LicenseManager licenseManager;

@Mock
private RuntimeSecretsService runtimeSecretsService;

@Before
public void setUp() throws Exception {
apiManager = spy(new ApiManagerImpl(eventManager, gatewayConfiguration, licenseManager, dataEncryptor));
apiManager = spy(new ApiManagerImpl(eventManager, gatewayConfiguration, licenseManager, dataEncryptor, runtimeSecretsService));
when(gatewayConfiguration.shardingTags()).thenReturn(Optional.empty());
when(gatewayConfiguration.hasMatchingTags(any())).thenCallRealMethod();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.gravitee.definition.model.DefinitionVersion;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

Expand All @@ -45,6 +46,8 @@ public abstract class ReactableApi<T> implements Reactable, Serializable {

private DefinitionContext definitionContext = new DefinitionContext();

private Map<String, String> deploymentProperties;

protected ReactableApi() {}

protected ReactableApi(T definition) {
Expand Down Expand Up @@ -115,6 +118,14 @@ public void setDefinitionContext(DefinitionContext definitionContext) {
this.definitionContext = definitionContext;
}

public void setDeploymentProperties(Map<String, String> deploymentProperties) {
this.deploymentProperties = deploymentProperties;
}

public Map<String, String> getDeploymentProperties() {
return deploymentProperties;
}

public T getDefinition() {
return this.definition;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@ public Maybe<ReactableApi<?>> to(Event apiEvent) {

// Update definition with required information for deployment phase
reactableApi = new io.gravitee.gateway.handlers.api.definition.Api(eventApiDefinition);
reactableApi.setDeploymentProperties(apiEvent.getProperties());
} else {
var eventApiDefinition = objectMapper.readValue(api.getDefinition(), io.gravitee.definition.model.v4.Api.class);

// Update definition with required information for deployment phase
reactableApi = new io.gravitee.gateway.reactive.handlers.api.v4.Api(eventApiDefinition);
reactableApi.setDeploymentProperties(apiEvent.getProperties());
}

reactableApi.setEnabled(api.getLifecycleState() == LifecycleState.STARTED);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.gravitee.gateway.standalone.secrets;

import io.gravitee.definition.model.services.secrets.ApiV4DefinitionBrowser;
import io.gravitee.definition.model.v4.Api;
import io.gravitee.node.api.secrets.runtime.discovery.DefinitionBrowser;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @author Benoit BORDIGONI (benoit.bordigoni at graviteesource.com)
* @author GraviteeSource Team
*/
@Configuration
public class DefinitionBrowserBeanFactory {

@Bean
DefinitionBrowser<Api> apiV4() {
return new ApiV4DefinitionBrowser();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import io.gravitee.gateway.repository.plugins.GatewayRepositoryScopeProvider;
import io.gravitee.gateway.standalone.node.GatewayNode;
import io.gravitee.gateway.standalone.node.GatewayNodeMetadataResolver;
import io.gravitee.gateway.standalone.secrets.DefinitionBrowserBeanFactory;
import io.gravitee.gateway.standalone.vertx.VertxReactorConfiguration;
import io.gravitee.node.api.Node;
import io.gravitee.node.api.NodeMetadataResolver;
Expand All @@ -62,6 +63,7 @@
PlatformConfiguration.class,
ConnectorConfiguration.class,
RequestConfiguration.class,
DefinitionBrowserBeanFactory.class,
}
)
public class StandaloneConfiguration {
Expand Down
Loading