@Test
public void testUpload() throws Exception {
UploadTest client = new UploadTest();
+ assertNotNull(client);
(new ClientMocking())
.errorOnNoAuth(401, "Unauthorized")
.errorOnBadAuth("acumosa", "acumosa", 403, "Forbidden")
"username": "nexususer",
"password": "nexuspass",
"nexus.group-id": "myorg"
- }
+ },
+ "verification.url": "http://securityserver:9999"
}'
Note that::
Separator between components of the path prefix within the Nexus repository.
The prefix is of the form groupid separator solutionid separator revisionid.
+verification.url
+ Required.
+
+ URL for the Acumos security-verification server used to perform security
+ verification scans on solution revisions.
+
=========================================
Federation Gateway Certificate Generation
=========================================
Version 2.3.0, 2019-08-09
-------------------------
-* Java code upgrade to Java 11 (`ACUMOS-3334 <https://jira.acumos.org/browse/ACUMOS-33334>`_)
+* Run SV license scan when a model has been federated (`ACUMOS-3396 <https://jira.acumos.org/browse/ACUMOS-3396>`_)
+ * This adds a new required configuration value, "verification.url" for the
+ security verification service.
+
+* Java code upgrade to Java 11 (`ACUMOS-3334 <https://jira.acumos.org/browse/ACUMOS-3334>`_)
* Update to CDS 2.2.6
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.acumos.security-verification</groupId>
+ <artifactId>security-verification-client</artifactId>
+ <version>0.0.24</version>
+ </dependency>
<!-- Compile time only dependencies -->
<dependency>
<groupId>org.projectlombok</groupId>
return new DockerConfig();
}
+ @Bean
+ @ConfigurationProperties(prefix="verification")
+ ServiceConfig verificationConfig() {
+ return new ServiceConfig();
+ }
+
@Bean
Clients clients() {
return new Clients();
import org.acumos.federation.client.ClientBase;
import org.acumos.federation.client.FederationClient;
+import org.acumos.securityverification.service.ISecurityVerificationClientService;
+import org.acumos.securityverification.service.SecurityVerificationClientServiceImpl;
+
/**
* Defines all beans used to access outside services.
*
@Autowired
private DockerConfig dockerConfig;
+ @Autowired
+ private ServiceConfig verificationConfig;
+
private ICommonDataServiceRestClient cdsClient;
private NexusClient nexusClient;
+ private ISecurityVerificationClientService svClient;
public FederationClient getFederationClient(String url) {
/*
.build()
).build();
}
+
+ public synchronized ISecurityVerificationClientService getSVClient() {
+ if (svClient == null) {
+ svClient = new SecurityVerificationClientServiceImpl(
+ verificationConfig.getUrl(),
+ cdmsConfig.getUrl(),
+ cdmsConfig.getUsername(),
+ cdmsConfig.getPassword(),
+ nexusConfig.getUrl(),
+ nexusConfig.getUsername(),
+ nexusConfig.getPassword());
+ }
+ return svClient;
+ }
}
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.UriTemplateHandler;
@Secured(Security.ROLE_PEER)
@ApiOperation(value = "Invoked by Peer Acumos to get status and self information.", response = MLPPeer.class)
- @RequestMapping(value = FederationClient.PING_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.PING_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<MLPPeer> ping() {
log.debug("/ping");
@Secured(Security.ROLE_PARTNER)
@ApiOperation(value = "Invoked by Peer Acumos to get a list of peers from local Acumos Instance .", response = MLPPeer.class, responseContainer = "List")
- @RequestMapping(value = FederationClient.PEERS_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.PEERS_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<List<MLPPeer>> getPeers() {
log.debug("/peers");
@Secured(Security.ROLE_REGISTER)
@ApiOperation(value = "Invoked by another Acumos Instance to request federation.", response = MLPPeer.class)
- @RequestMapping(value = FederationClient.REGISTER_URI, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @PostMapping(value = FederationClient.REGISTER_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<MLPPeer> register() {
log.debug("/peer/register");
@Secured(Security.ROLE_UNREGISTER)
@ApiOperation(value = "Invoked by another Acumos Instance to request federation termination.", response = MLPPeer.class)
- @RequestMapping(value = FederationClient.UNREGISTER_URI, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @PostMapping(value = FederationClient.UNREGISTER_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<MLPPeer> unregister() {
log.debug("/peer/unregister");
@Secured(Security.ROLE_PEER)
@ApiOperation(value = "Invoked by Peer Acumos to get a list of visible Catalogs from the local Acumos Instance .", response = MLPCatalog.class, responseContainer = "List")
- @RequestMapping(value = FederationClient.CATALOGS_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.CATALOGS_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<List<MLPCatalog>> getCatalogs() {
log.debug("/catalogs");
@Secured(Security.ROLE_PEER)
@ApiOperation(value = "Invoked by Peer Acumos to get a list of Published Solutions from the Catalog of the local Acumos Instance .", response = MLPSolution.class, responseContainer = "List")
- @RequestMapping(value = FederationClient.SOLUTIONS_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.SOLUTIONS_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<List<MLPSolution>> getSolutions(@RequestParam(value="catalogId", required = true) String catalogId) {
log.debug("/solutions?catalogId={}", catalogId);
@Secured(Security.ROLE_PEER)
@ApiOperation(value = "Invoked by Peer Acumos to get a list detailed solution information from the Catalog of the local Acumos Instance .", response = MLPSolution.class)
- @RequestMapping(value = FederationClient.SOLUTION_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.SOLUTION_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<MLPSolution> getSolution(@PathVariable("solutionId") String solutionId) {
log.debug("/solutions/{}", solutionId);
@Secured(Security.ROLE_PEER)
@ApiOperation(value = "Invoked by Peer Acumos to get a list of Solution Revision from the Catalog of the local Acumos Instance .", response = MLPSolutionRevision.class, responseContainer = "List")
- @RequestMapping(value = FederationClient.REVISIONS_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.REVISIONS_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<List<MLPSolutionRevision>> getRevisions(@PathVariable("solutionId") String solutionId) {
log.debug("/solutions/{}/revisions", solutionId);
@Secured(Security.ROLE_PEER)
@ApiOperation(value = "Invoked by peer Acumos to get solution revision details from the local Acumos Instance .", response = MLPSolutionRevision.class)
- @RequestMapping(value = FederationClient.REVISION_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.REVISION_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<MLPSolutionRevision> getRevision(
@PathVariable("solutionId") String solutionId,
@Secured(Security.ROLE_PEER)
@ApiOperation(value = "Invoked by Peer Acumos to get a list of solution revision artifacts from the local Acumos Instance .", response = MLPArtifact.class, responseContainer = "List")
- @RequestMapping(value = FederationClient.ARTIFACTS_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.ARTIFACTS_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<List<MLPArtifact>> getArtifacts(
@PathVariable("solutionId") String solutionId,
@Secured(Security.ROLE_PEER)
@ApiOperation(value = "Invoked by Peer Acumos to get a list of solution revision public documents from the local Acumos Instance .", response = MLPArtifact.class, responseContainer = "List")
- @RequestMapping(value = FederationClient.DOCUMENTS_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.DOCUMENTS_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<List<MLPDocument>> getDocuments(
@PathVariable("revisionId") String revisionId,
@Secured(Security.ROLE_PEER)
@ApiOperation(value = "API to download artifact content", response = Resource.class, code = 200)
- @RequestMapping(value = FederationClient.ARTIFACT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
+ @GetMapping(value = FederationClient.ARTIFACT_URI, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public Callable<Resource> getArtifactContent(@PathVariable("artifactId") String artifactId) {
log.debug("/artifacts/{}/content", artifactId);
@Secured(Security.ROLE_PEER)
@ApiOperation(value = "API to download document content", response = Resource.class, code = 200)
- @RequestMapping(value = FederationClient.DOCUMENT_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
+ @GetMapping(value = FederationClient.DOCUMENT_URI, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public Resource getDocumentContent(@PathVariable("documentId") String documentId) {
log.debug("/documents/{}/content", documentId);
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.security.access.annotation.Secured;
private SubscriptionPoller poller;
@ApiOperation(value = "Invoked by local Acumos to get a list of catalogs available from a peer Acumos instance .", response = MLPCatalog.class, responseContainer = "List")
- @RequestMapping(value = FederationClient.CATALOGS_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.CATALOGS_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<List<MLPCatalog>> getCatalogs(
HttpServletResponse response,
}
@ApiOperation(value = "Invoked by local Acumos to get a list of solutions available from a peer Acumos instance .", response = MLPSolution.class, responseContainer = "List")
- @RequestMapping(value = FederationClient.SOLUTIONS_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.SOLUTIONS_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<List<MLPSolution>> getSolutions(
HttpServletResponse response,
}
@ApiOperation(value = "Invoked by local Acumos to get detailed solution information from the catalog of a peer acumos Instance.", response = MLPSolution.class)
- @RequestMapping(value = FederationClient.SOLUTION_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.SOLUTION_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<MLPSolution> getSolution(
HttpServletResponse response,
}
@ApiOperation(value = "Invoked by local Acumos to get peers information from remote Acumos peer.", response = MLPPeer.class, responseContainer = "List")
- @RequestMapping(value = FederationClient.PEERS_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.PEERS_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<List<MLPPeer>> getPeers(
HttpServletResponse response,
}
@ApiOperation(value = "Invoked by local Acumos to get peer Acumos status and information.", response = MLPPeer.class)
- @RequestMapping(value = FederationClient.PING_URI, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @GetMapping(value = FederationClient.PING_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<MLPPeer> ping(
HttpServletResponse response,
}
@ApiOperation(value = "Invoked by local Acumos to register with a remote Acumos peer.", response = MLPPeer.class)
- @RequestMapping(value = FederationClient.REGISTER_URI, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @PostMapping(value = FederationClient.REGISTER_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<MLPPeer> register(
HttpServletResponse response,
}
@ApiOperation(value = "Invoked by other Acumos components in order to trigger subscription execution")
- @RequestMapping(value = GatewayClient.SUBSCRIPTION_URI, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @PostMapping(value = GatewayClient.SUBSCRIPTION_URI, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public JsonResponse<Void> triggerPeerSubscription(
HttpServletResponse response,
if (changed && !isnew) {
catalogService.updateRevision(pRev);
}
+ if (changed) {
+ new Thread(() -> { try {clients.getSVClient().securityVerificationScan(solutionId, revisionId, "created", userId); } catch (Exception e) { log.error("SV scan failure on revision " + revisionId, e); }}).start();
+ }
return changed;
}
"nexus.name-separator=,",
"nexus.url=http://nexus.example.org",
"docker.host=tcp://localhost:999",
- "cdms.client.url=http://cdms.example.org"
+ "cdms.client.url=http://cdms.example.org",
+ "verification.url=http://svserver.example.org"
}
)
public class ClientsTest {
assertEquals(clients.getCDSClient(), clients.getCDSClient());
assertEquals(clients.getNexusClient(), clients.getNexusClient());
assertNotNull(clients.getDockerClient());
+ assertEquals(clients.getSVClient(), clients.getSVClient());
}
}
@Test
public void testSwagger() throws Exception {
RawAnonClient rac = new RawAnonClient("https://localhost:" + port);
+ assertNotNull(rac);
rac.get("/swagger-ui.html");
rac.get("/v2/api-docs");
}
import org.junit.Before;
import org.junit.runner.RunWith;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.any;
-
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
import org.acumos.cds.client.ICommonDataServiceRestClient;
import org.acumos.cds.client.CommonDataServiceRestClientImpl;
+import org.acumos.securityverification.service.ISecurityVerificationClientService;
+
import org.acumos.federation.client.FederationClient;
import org.acumos.federation.client.GatewayClient;
import org.acumos.federation.client.ClientBase;
docker = new SimulatedDockerClient();
when(clients.getDockerClient()).thenReturn(docker.getClient());
+
+ ISecurityVerificationClientService sv = mock(ISecurityVerificationClientService.class);
+ when (clients.getSVClient()).thenReturn(sv);
}
@Test
@Test
public void testSwagger() throws Exception {
RawAnonClient rac = new RawAnonClient("https://localhost:" + port);
+ assertNotNull(rac);
rac.get("/swagger-ui.html");
rac.get("/v2/api-docs");
}