Skip to content

Commit

Permalink
[backend/frontend] Add Assets & AssetGroups (#481)
Browse files Browse the repository at this point in the history
  • Loading branch information
RomuDeuxfois authored Jan 22, 2024
1 parent 32e7175 commit ec76bdb
Show file tree
Hide file tree
Showing 96 changed files with 4,585 additions and 271 deletions.
1 change: 1 addition & 0 deletions .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ services:

---
kind: pipeline
type: docker
name: openex-tests-master

trigger:
Expand Down
25 changes: 20 additions & 5 deletions openex-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@
<bcpg-jdk15on.version>1.70</bcpg-jdk15on.version>
<commons-collections4.version>4.4</commons-collections4.version>
<commons-email.version>1.5</commons-email.version>
<commons-validator.version>1.8.0</commons-validator.version>
<flyway.version>9.0.3</flyway.version>
<opensaml.version>4.1.1</opensaml.version>
<springdoc.version>1.7.0</springdoc.version>
<springdoc.version>2.3.0</springdoc.version>
<springdoc-plugin.version>1.4</springdoc-plugin.version>
<jacoco-plugin.version>0.8.11</jacoco-plugin.version>
</properties>

<profiles>
Expand All @@ -49,11 +47,21 @@
<artifactId>openex-injector-http</artifactId>
<version>3.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.openex</groupId>
<artifactId>openex-injector-caldera</artifactId>
<version>3.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.openex</groupId>
<artifactId>openex-collector-users</artifactId>
<version>3.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.openex</groupId>
<artifactId>openex-collector-caldera</artifactId>
<version>3.5.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
</profiles>
Expand Down Expand Up @@ -107,12 +115,12 @@
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webflux-ui</artifactId>
<artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
<version>${springdoc.version}</version>
</dependency>
<dependency>
Expand Down Expand Up @@ -189,6 +197,7 @@
<artifactId>opensaml-saml-impl</artifactId>
<version>${opensaml.version}</version>
</dependency>
<!-- TEST -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand All @@ -200,6 +209,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
Expand Down Expand Up @@ -272,6 +286,7 @@
</execution>
</executions>
<configuration>
<!-- UI Api Docs: http://localhost:8080/swagger-ui/index.html -->
<apiDocsUrl>http://localhost:8080/api-docs</apiDocsUrl>
<outputFileName>swagger.json</outputFileName>
<outputDir>.</outputDir>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package io.openex.migration;

import org.flywaydb.core.api.migration.BaseJavaMigration;
import org.flywaydb.core.api.migration.Context;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.Statement;

@Component
public class V2_68__Assets_Asset_Groups extends BaseJavaMigration {

@Override
public void migrate(Context context) throws Exception {
Connection connection = context.getConnection();
Statement select = connection.createStatement();
// Add extension
select.execute("""
CREATE EXTENSION IF NOT EXISTS hstore;
""");
// Create table asset
select.execute("""
CREATE TABLE IF NOT EXISTS assets (
asset_id varchar(255) not null constraint assets_pkey primary key,
asset_type varchar(255) not null,
asset_sources hstore,
asset_blobs hstore,
asset_name varchar(255) not null,
asset_description text,
asset_last_seen timestamp,
asset_created_at timestamp not null default now(),
asset_updated_at timestamp not null default now()
);
CREATE INDEX IF NOT EXISTS idx_assets on assets (asset_id);
""");
// Add column for endpoint type
select.execute("""
ALTER TABLE assets ADD COLUMN endpoint_ips text[];
ALTER TABLE assets ADD COLUMN endpoint_hostname varchar(255);
ALTER TABLE assets ADD COLUMN endpoint_platform varchar(255) not null;
ALTER TABLE assets ADD COLUMN endpoint_mac_addresses text[];
""");
// Add association table between asset and tag
select.execute("""
CREATE TABLE assets_tags (
asset_id varchar(255) not null constraint asset_id_fk references assets,
tag_id varchar(255) not null constraint tag_id_fk references tags,
constraint assets_tags_pkey primary key (asset_id, tag_id)
);
CREATE INDEX idx_assets_tags_asset on assets_tags (asset_id);
CREATE INDEX idx_assets_tags_tag on assets_tags (tag_id);
""");
// Create table asset groups
select.execute("""
CREATE TABLE IF NOT EXISTS asset_groups (
asset_group_id varchar(255) not null constraint asset_groups_pkey primary key,
asset_group_name varchar(255) not null,
asset_group_description text,
asset_group_created_at timestamp not null default now(),
asset_group_updated_at timestamp not null default now()
);
CREATE INDEX IF NOT EXISTS idx_asset_groups on asset_groups (asset_group_id);
""");
// Add association table between asset group and tag
select.execute("""
CREATE TABLE asset_groups_tags (
asset_group_id varchar(255) not null constraint asset_group_id_fk references asset_groups on delete cascade,
tag_id varchar(255) not null constraint tag_id_fk references tags on delete cascade,
constraint asset_groups_tags_pkey primary key (asset_group_id, tag_id)
);
CREATE INDEX idx_asset_groups_tags_asset_group on asset_groups_tags (asset_group_id);
CREATE INDEX idx_asset_groups_tags_tag on asset_groups_tags (tag_id);
""");
// Add association table between asset and asset groups
select.execute("""
CREATE TABLE IF NOT EXISTS asset_groups_assets (
asset_group_id varchar(255) not null constraint asset_group_id_fk references asset_groups on delete cascade,
asset_id varchar(255) not null constraint asset_id_fk references assets on delete cascade,
constraint asset_groups_assets_pkey primary key (asset_group_id, asset_id)
);
CREATE INDEX IF NOT EXISTS idx_asset_groups_assets_asset_group on asset_groups_assets (asset_group_id);
CREATE INDEX IF NOT EXISTS idx_asset_groups_assets_asset on asset_groups_assets (asset_id);
""");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.openex.migration;

import org.flywaydb.core.api.migration.BaseJavaMigration;
import org.flywaydb.core.api.migration.Context;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.Statement;

@Component
public class V2_69__Modify_Inject_async_ids extends BaseJavaMigration {

@Override
public void migrate(Context context) throws Exception {
Connection connection = context.getConnection();
Statement select = connection.createStatement();
// Modify inject async ids property
select.execute("""
ALTER TABLE injects_statuses ADD COLUMN status_async_ids text[];
UPDATE injects_statuses SET status_async_ids = ARRAY[status_async_id];
ALTER TABLE injects_statuses DROP COLUMN status_async_id;
""");
}
}
2 changes: 1 addition & 1 deletion openex-api/src/main/java/io/openex/rest/HomeApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ private static String readResourceAsString(Resource resource) {
@Value("${server.servlet.context-path}")
private String contextPath;

@GetMapping(path = {"/", "/{path:^(?!api$|login$|logout$|oauth2$|saml2$|static$).*$}/**"}, produces = MediaType.TEXT_HTML_VALUE)
@GetMapping(path = {"/", "/{path:^(?!api$|login$|logout$|oauth2$|saml2$|static$|swagger-ui$).*$}/**"}, produces = MediaType.TEXT_HTML_VALUE)
public ResponseEntity<String> home() {
ClassPathResource classPathResource = new ClassPathResource("/build/index.html");
String index = readResourceAsString(classPathResource);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package io.openex.rest.asset.endpoint;

import io.openex.database.model.Endpoint;
import io.openex.database.repository.TagRepository;
import io.openex.rest.asset.endpoint.form.EndpointInput;
import io.openex.service.AssetEndpointService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;

import static io.openex.database.model.User.ROLE_ADMIN;
import static io.openex.helper.StreamHelper.fromIterable;

@RequiredArgsConstructor
@RestController
public class EndpointApi {

public static final String ENDPOINT_URI = "/api/endpoints";

private final AssetEndpointService assetEndpointService;
private final TagRepository tagRepository;

@PostMapping(ENDPOINT_URI)
@Secured(ROLE_ADMIN)
public Endpoint createEndpoint(@Valid @RequestBody final EndpointInput input) {
Endpoint endpoint = new Endpoint();
endpoint.setUpdateAttributes(input);
endpoint.setPlatform(input.getPlatform());
endpoint.setTags(fromIterable(this.tagRepository.findAllById(input.getTagIds())));
return this.assetEndpointService.createEndpoint(endpoint);
}

@GetMapping(ENDPOINT_URI)
@PreAuthorize("isObserver()")
public List<Endpoint> endpoints() {
return this.assetEndpointService.endpoints();
}

@PutMapping(ENDPOINT_URI + "/{endpointId}")
@Secured(ROLE_ADMIN)
public Endpoint updateEndpoint(
@PathVariable @NotBlank final String endpointId,
@Valid @RequestBody final EndpointInput input) {
Endpoint endpoint = this.assetEndpointService.endpoint(endpointId);
endpoint.setUpdateAttributes(input);
endpoint.setPlatform(input.getPlatform());
endpoint.setTags(fromIterable(this.tagRepository.findAllById(input.getTagIds())));
return this.assetEndpointService.updateEndpoint(endpoint);
}

@DeleteMapping(ENDPOINT_URI + "/{endpointId}")
@Secured(ROLE_ADMIN)
public void deleteEndpoint(@PathVariable @NotBlank final String endpointId) {
this.assetEndpointService.deleteEndpoint(endpointId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.openex.rest.asset.endpoint.form;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.openex.database.model.Endpoint;
import io.openex.rest.asset.form.AssetInput;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;

import static io.openex.config.AppConfig.MANDATORY_MESSAGE;

@EqualsAndHashCode(callSuper = true)
@Data
public class EndpointInput extends AssetInput {

@NotEmpty(message = MANDATORY_MESSAGE)
@Size(min = 1, message = MANDATORY_MESSAGE)
@JsonProperty("endpoint_ips")
private String[] ips;

@JsonProperty("endpoint_hostname")
private String hostname;

@NotNull(message = MANDATORY_MESSAGE)
@JsonProperty("endpoint_platform")
private Endpoint.PLATFORM_TYPE platform;

@JsonProperty("endpoint_mac_adresses")
private String[] macAdresses;

}
30 changes: 30 additions & 0 deletions openex-api/src/main/java/io/openex/rest/asset/form/AssetInput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.openex.rest.asset.form;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import jakarta.validation.constraints.NotBlank;

import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

import static io.openex.config.AppConfig.MANDATORY_MESSAGE;

@Data
public abstract class AssetInput {

@NotBlank(message = MANDATORY_MESSAGE)
@JsonProperty("asset_name")
private String name;

@JsonProperty("asset_description")
private String description;

@JsonProperty("asset_last_seen")
private Instant lastSeen;

@JsonProperty("asset_tags")
private List<String> tagIds = new ArrayList<>();

}
Loading

0 comments on commit ec76bdb

Please sign in to comment.