From 8eef21c9481f795500a0a5d995deb2bdabf1899d Mon Sep 17 00:00:00 2001 From: Kevin Doran Date: Tue, 29 May 2018 12:13:06 -0400 Subject: [PATCH 1/2] NIFIREG-172 Adds Swagger UI - Adds self-hosted Swagger UI to nifi-registry-web-api WAR at /swagger/ui.html - Updates NOTICE for included ALv2 licensed source. - Adds Jersey filter exclusion for resources starting with /swagger/* - Adds top-level authorizable resource type for /swagger/* - Updates ResourceAuthorizationFilter configuration to include swagger resource type - Corrects name of Position model object in Swagger specification - Corrects duplicate operationId/nickname field for methods in FlowResource and BucketFlowResource --- NOTICE | 10 +- nifi-registry-assembly/NOTICE | 47 ++++---- .../apache/nifi/registry/flow/Position.java | 2 +- .../authorization/AuthorizableLookup.java | 7 ++ .../StandardAuthorizableLookup.java | 20 ++++ .../file/FileAccessPolicyProvider.java | 3 + .../resource/ResourceFactory.java | 26 +++++ .../authorization/resource/ResourceType.java | 3 +- .../service/AuthorizationService.java | 3 + .../service/AuthorizationServiceSpec.groovy | 6 +- nifi-registry-web-api/pom.xml | 109 +++++++++++++++++- .../web/NiFiRegistryResourceConfig.java | 4 +- .../nifi/registry/web/api/FlowResource.java | 5 + .../security/NiFiRegistrySecurityConfig.java | 1 + .../nifi/registry/web/api/SecureFileIT.java | 1 + pom.xml | 1 + 16 files changed, 217 insertions(+), 31 deletions(-) diff --git a/NOTICE b/NOTICE index e2172aa1d..8409aaed8 100644 --- a/NOTICE +++ b/NOTICE @@ -1,9 +1,13 @@ Apache NiFi Registry -Copyright 2014-2017 The Apache Software Foundation +Copyright 2014-2018 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). This includes derived works from the Apache NiFi (ASLv2 licensed) project (https://git-wip-us.apache.org/repos/asf?p=nifi.git): - Copyright 2015-2017 The Apache Software Foundation - This includes sources for bootstrapping, runtime, component API, security/authorization API \ No newline at end of file + Copyright 2015-2018 The Apache Software Foundation + This includes sources for bootstrapping, runtime, component API, security/authorization API + +This includes derived works from the Apache NiFi MiNiFi (ASLv2 licensed) project (https://git-wip-us.apache.org/repos/asf/nifi-minifi.git): + Copyright 2015-2018 The Apache Software Foundation + This includes build configuration for the Swagger UI. diff --git a/nifi-registry-assembly/NOTICE b/nifi-registry-assembly/NOTICE index a2214e36f..8d1829fe6 100644 --- a/nifi-registry-assembly/NOTICE +++ b/nifi-registry-assembly/NOTICE @@ -163,29 +163,29 @@ The following binary components are provided under the Apache Software License v Apache log4j Copyright 2010 The Apache Software Foundation - (ASLv2) Spring Framework - The following NOTICE information applies: - Spring Framework 5.0.2.RELEASE - Copyright (c) 2002-2017 Pivotal, Inc. + (ASLv2) Spring Framework + The following NOTICE information applies: + Spring Framework 5.0.2.RELEASE + Copyright (c) 2002-2017 Pivotal, Inc. - (ASLv2) Spring Security - The following NOTICE information applies: - Spring Framework 5.0.5.RELEASE - Copyright (c) 2002-2017 Pivotal, Inc. + (ASLv2) Spring Security + The following NOTICE information applies: + Spring Framework 5.0.5.RELEASE + Copyright (c) 2002-2017 Pivotal, Inc. - This product includes software developed by Spring Security - Project (http://www.springframework.org/security). + This product includes software developed by Spring Security + Project (http://www.springframework.org/security). - (ASLv2) Spring LDAP - The following NOTICE information applies: - Spring LDAP 2.3.2.RELEASE - Copyright (c) 2002-2017 Pivotal, Inc. + (ASLv2) Spring LDAP + The following NOTICE information applies: + Spring LDAP 2.3.2.RELEASE + Copyright (c) 2002-2017 Pivotal, Inc. - This product includes software developed by the Spring LDAP - Project (http://www.springframework.org/ldap). + This product includes software developed by the Spring LDAP + Project (http://www.springframework.org/ldap). - (ASLv2) Apache Tomcat Embed EL - The following NOTICE information applies: + (ASLv2) Apache Tomcat Embed EL + The following NOTICE information applies: Apache Tomcat Copyright 1999-2017 The Apache Software Foundation @@ -242,9 +242,14 @@ The following binary components are provided under the Apache Software License v may be obtained from: http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/index.html - (ASLv2) SnakeYAML - The following NOTICE information applies: - Copyright (c) 2008, http://www.snakeyaml.org + (ASLv2) SnakeYAML + The following NOTICE information applies: + Copyright (c) 2008, http://www.snakeyaml.org + + (ASLv2) Swagger UI + The following NOTICE information applies: + Copyright 2017 SmartBear Software + ************************ Common Development and Distribution License 1.1 diff --git a/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/Position.java b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/Position.java index 2b4574c27..bee14d293 100644 --- a/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/Position.java +++ b/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/Position.java @@ -23,7 +23,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -@ApiModel("The position of a component on the graph") +@ApiModel(description = "The position of a component on the graph") public class Position { private double x; private double y; diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizableLookup.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizableLookup.java index 18421993a..49db37a03 100644 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizableLookup.java +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizableLookup.java @@ -27,6 +27,13 @@ public interface AuthorizableLookup { */ Authorizable getActuatorAuthorizable(); + /** + * Get the authorizable for /swagger. + * + * @return authorizable + */ + Authorizable getSwaggerAuthorizable(); + /** * Get the authorizable for /proxy. * diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java index 50b7185fe..18c2a52d7 100644 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java @@ -91,11 +91,28 @@ public Resource getResource() { } }; + private static final Authorizable SWAGGER_AUTHORIZABLE = new Authorizable() { + @Override + public Authorizable getParentAuthorizable() { + return null; + } + + @Override + public Resource getResource() { + return ResourceFactory.getSwaggerResource(); + } + }; + @Override public Authorizable getActuatorAuthorizable() { return ACTUATOR_AUTHORIZABLE; } + @Override + public Authorizable getSwaggerAuthorizable() { + return SWAGGER_AUTHORIZABLE; + } + @Override public Authorizable getProxyAuthorizable() { return PROXY_AUTHORIZABLE; @@ -161,6 +178,9 @@ private Authorizable getAuthorizableByResource(final ResourceType resourceType, case Actuator: authorizable = getActuatorAuthorizable(); break; + case Swagger: + authorizable = getSwaggerAuthorizable(); + break; /* Access to buckets can be authorized by the top-level /buckets resource or an individual /buckets/{id} resource */ case Bucket: diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java index 83ceb5051..c3434c432 100644 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java @@ -128,6 +128,9 @@ private static JAXBContext initializeJaxbContext(final String contextPath) { new ResourceActionPair("/actuator", READ_CODE), new ResourceActionPair("/actuator", WRITE_CODE), new ResourceActionPair("/actuator", DELETE_CODE), + new ResourceActionPair("/swagger", READ_CODE), + new ResourceActionPair("/swagger", WRITE_CODE), + new ResourceActionPair("/swagger", DELETE_CODE), new ResourceActionPair("/proxy", WRITE_CODE) }; diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceFactory.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceFactory.java index 845e7191e..c605d4a6d 100644 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceFactory.java +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceFactory.java @@ -108,6 +108,23 @@ public String getSafeDescription() { } }; + private final static Resource SWAGGER_RESOURCE = new Resource() { + @Override + public String getIdentifier() { + return ResourceType.Swagger.getValue(); + } + + @Override + public String getName() { + return "Swagger"; + } + + @Override + public String getSafeDescription() { + return "swagger"; + } + }; + /** * Gets the Resource for actuator system management endpoints. * @@ -117,6 +134,15 @@ public static Resource getActuatorResource() { return ACTUATOR_RESOURCE; } + /** + * Gets the Resource for swagger UI static resources. + * + * @return The resource for swagger UI static resources. + */ + public static Resource getSwaggerResource() { + return SWAGGER_RESOURCE; + } + /** * Gets the Resource for proxying a user request. * diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceType.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceType.java index 00358ffea..0b77cd20a 100644 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceType.java +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ResourceType.java @@ -21,7 +21,8 @@ public enum ResourceType { Policy("/policies"), Proxy("/proxy"), Tenant("/tenants"), - Actuator("/actuator"); + Actuator("/actuator"), + Swagger("/swagger"); final String value; diff --git a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java index 12f6f2670..204f96689 100644 --- a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java +++ b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java @@ -530,6 +530,9 @@ private List getAuthor if (includeFilter == null || includeFilter.equals(ResourceType.Actuator)) { resources.add(ResourceFactory.getActuatorResource()); } + if (includeFilter == null || includeFilter.equals(ResourceType.Swagger)) { + resources.add(ResourceFactory.getSwaggerResource()); + } if (includeFilter == null || includeFilter.equals(ResourceType.Bucket)) { resources.add(ResourceFactory.getBucketsResource()); // add all buckets diff --git a/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/service/AuthorizationServiceSpec.groovy b/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/service/AuthorizationServiceSpec.groovy index 8bde97a91..149ec3619 100644 --- a/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/service/AuthorizationServiceSpec.groovy +++ b/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/service/AuthorizationServiceSpec.groovy @@ -536,7 +536,7 @@ class AuthorizationServiceSpec extends Specification { then: resources != null - resources.size() == 7 + resources.size() == 8 def sortedResources = resources.sort{it.identifier} sortedResources[0].identifier == "/actuator" sortedResources[1].identifier == "/buckets" @@ -544,7 +544,8 @@ class AuthorizationServiceSpec extends Specification { sortedResources[3].identifier == "/buckets/b2" sortedResources[4].identifier == "/policies" sortedResources[5].identifier == "/proxy" - sortedResources[6].identifier == "/tenants" + sortedResources[6].identifier == "/swagger" + sortedResources[7].identifier == "/tenants" } @@ -582,6 +583,7 @@ class AuthorizationServiceSpec extends Specification { authorizableLookup.getAuthorizableByResource("/buckets/b2") >> denied authorizableLookup.getAuthorizableByResource("/policies") >> authorized authorizableLookup.getAuthorizableByResource("/proxy") >> denied + authorizableLookup.getAuthorizableByResource("/swagger") >> denied authorizableLookup.getAuthorizableByResource("/tenants") >> authorized diff --git a/nifi-registry-web-api/pom.xml b/nifi-registry-web-api/pom.xml index e991836ab..e044d9031 100644 --- a/nifi-registry-web-api/pom.xml +++ b/nifi-registry-web-api/pom.xml @@ -89,7 +89,7 @@ ${project.build.directory}/${project.artifactId}-${project.version}/docs/rest-api/index.html - ${project.build.directory}/swagger-ui + ${project.build.directory}/swagger @@ -116,9 +116,116 @@ + + com.googlecode.maven-download-plugin + download-maven-plugin + 1.2.1 + + + download-swagger-ui + + + wget + + + + https://github.com/swagger-api/swagger-ui/archive/v${swagger.ui.version}.tar.gz + + true + ${project.build.directory} + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.8 + + + bundle-swagger-ui + prepare-package + + run + + + + + Copy static Swagger UI files to target + + + + + + Disable schema validation by removing validatorUrl + + + + + Rename 'index.html' to 'ui.html' + + Replace default swagger.json location + + + + Copy swagger.json into static assets folder + + + + + + + + + + + + + + no-swagger-ui + + + + + com.googlecode.maven-download-plugin + download-maven-plugin + 1.2.1 + + + download-swagger-ui + none + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.8 + + + bundle-swagger-ui + none + + + + + + + + org.springframework.boot diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java index 097fc473a..ef0f97e95 100644 --- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java +++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java @@ -69,8 +69,8 @@ public NiFiRegistryResourceConfig(@Context ServletContext servletContext) { // so it can directly set the HttpServletResponse instead of indirectly through a JAX-RS Response property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, true); - // configure jersey to ignore resource paths for actuator - property(ServletProperties.FILTER_STATIC_CONTENT_REGEX, "/actuator.*"); + // configure jersey to ignore resource paths for actuator and swagger-ui + property(ServletProperties.FILTER_STATIC_CONTENT_REGEX, "/(actuator|swagger/).*"); } } diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/FlowResource.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/FlowResource.java index 02283341b..afb8e11ad 100644 --- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/FlowResource.java +++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/FlowResource.java @@ -94,6 +94,7 @@ public Response getAvailableFlowFields() { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Gets a flow", + nickname = "globalGetFlow", response = VersionedFlow.class, extensions = { @Extension(name = "access-policy", properties = { @@ -133,6 +134,7 @@ public Response getFlow( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Gets summary information for all versions of a flow. Versions are ordered newest->oldest.", + nickname = "globalGetFlowVersions", response = VersionedFlowSnapshotMetadata.class, responseContainer = "List", extensions = { @@ -174,6 +176,7 @@ public Response getFlowVersions( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Gets the given version of a flow", + nickname = "globalGetFlowVersion", response = VersionedFlowSnapshot.class, extensions = { @Extension(name = "access-policy", properties = { @@ -215,6 +218,7 @@ public Response getFlowVersion( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Get the latest version of a flow", + nickname = "globalGetLatestFlowVersion", response = VersionedFlowSnapshot.class, extensions = { @Extension(name = "access-policy", properties = { @@ -253,6 +257,7 @@ public Response getLatestFlowVersion( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Get the metadata for the latest version of a flow", + nickname = "globalGetLatestFlowVersionMetadata", response = VersionedFlowSnapshotMetadata.class, extensions = { @Extension(name = "access-policy", properties = { diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/NiFiRegistrySecurityConfig.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/NiFiRegistrySecurityConfig.java index 1d484c136..a2a6ea95f 100644 --- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/NiFiRegistrySecurityConfig.java +++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/NiFiRegistrySecurityConfig.java @@ -165,6 +165,7 @@ private ResourceAuthorizationFilter resourceAuthorizationFilter() { resourceAuthorizationFilter = ResourceAuthorizationFilter.builder() .setAuthorizationService(authorizationService) .addResourceType(ResourceType.Actuator) + .addResourceType(ResourceType.Swagger) .build(); } return resourceAuthorizationFilter; diff --git a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureFileIT.java b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureFileIT.java index 29cd21577..67cb2e274 100644 --- a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureFileIT.java +++ b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureFileIT.java @@ -86,6 +86,7 @@ public void testRetrieveResources() throws Exception { // Given: an empty registry returns these resources String expected = "[" + "{\"identifier\":\"/actuator\",\"name\":\"Actuator\"}," + + "{\"identifier\":\"/swagger\",\"name\":\"Swagger\"}," + "{\"identifier\":\"/policies\",\"name\":\"Access Policies\"}," + "{\"identifier\":\"/tenants\",\"name\":\"Tenants\"}," + "{\"identifier\":\"/proxy\",\"name\":\"Proxy User Requests\"}," + diff --git a/pom.xml b/pom.xml index 86deaa4c6..aa3f8bc60 100644 --- a/pom.xml +++ b/pom.xml @@ -113,6 +113,7 @@ 2.0.2.RELEASE 5.0.5.RELEASE 4.2.0 + 3.12.0 From 3ad5c4ccddb56b08e8eb191bab17710827934d78 Mon Sep 17 00:00:00 2001 From: Kevin Doran Date: Wed, 13 Jun 2018 13:05:38 -0400 Subject: [PATCH 2/2] - Updates and fixes to README and NOTICE files --- README.md | 14 ++++++++++---- nifi-registry-assembly/NOTICE | 2 +- nifi-registry-assembly/README.md | 4 ++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 73ca2cb13..c7c3a9ed8 100644 --- a/README.md +++ b/README.md @@ -51,14 +51,20 @@ Registry—a subproject of Apache NiFi—is a complementary application that pro cd nifi-registry-assembly/target/nifi-registry--bin/nifi-registry-/ ./bin/nifi-registry.sh start + + Note that the application web server can take a while to load before it is accessible. -4) Launch the application +4) Accessing the application web UI - With the default settings, the application will be available at [http://localhost:18080/nifi-registry](http://localhost:18080/nifi-registry) + With the default settings, the application UI will be available at [http://localhost:18080/nifi-registry](http://localhost:18080/nifi-registry) -5) Logging +5) Accessing the application REST API + + If you wish to test against the application REST API, you can access the REST API directly. With the default settings, the base URL of the REST API will be at `http://localhost:18080/nifi-registry-api`. A UI for testing the REST API will be available at [http://localhost:18080/nifi-registry-api/swagger/ui.html](http://localhost:18080/nifi-registry-api/swagger/ui.html) + +6) Accessing the application logs - Logs will be available in logs/nifi-registry.app.log + Logs will be available in `logs/nifi-registry-app.log` ## License diff --git a/nifi-registry-assembly/NOTICE b/nifi-registry-assembly/NOTICE index 8d1829fe6..d5594aae1 100644 --- a/nifi-registry-assembly/NOTICE +++ b/nifi-registry-assembly/NOTICE @@ -1,5 +1,5 @@ Apache NiFi Registry -Copyright 2014-2017 The Apache Software Foundation +Copyright 2014-2018 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/nifi-registry-assembly/README.md b/nifi-registry-assembly/README.md index fd53a3092..00fc09c9c 100644 --- a/nifi-registry-assembly/README.md +++ b/nifi-registry-assembly/README.md @@ -29,9 +29,9 @@ Registry—a subproject of Apache NiFi—is a complementary application that pro ## Getting Started -To start NiFi: +To start NiFi Registry: - [linux/osx] execute bin/nifi-registry.sh start -- [windows] execute bin/start-nifi-registry.bat +- [windows] execute bin/run-nifi-registry.bat - Direct your browser to http://localhost:18080/nifi-registry/ ## Getting Help