This is an automated email from the ASF dual-hosted git repository. mcgilman pushed a commit to branch NIFI-15343 in repository https://gitbox.apache.org/repos/asf/nifi.git
commit b81a32fc857fab81245c39bb24b2b3a57b7a908a Author: Matt Gilman <[email protected]> AuthorDate: Mon Dec 15 13:11:06 2025 -0500 NIFI-15343: Adding an endpoint to return available secrets to the connector configuration wizard. --- .../org/apache/nifi/web/api/dto/SecretDTO.java | 69 ++++++++++++++++++++ .../apache/nifi/web/api/entity/SecretsEntity.java | 43 ++++++++++++ .../org/apache/nifi/web/NiFiServiceFacade.java | 13 ++++ .../apache/nifi/web/StandardNiFiServiceFacade.java | 23 +++++++ .../org/apache/nifi/web/api/ConnectorResource.java | 48 ++++++++++++++ .../org/apache/nifi/web/api/dto/DtoFactory.java | 21 ++++++ .../org/apache/nifi/web/api/dto/EntityFactory.java | 7 ++ .../nifi/web/controller/ControllerFacade.java | 10 +++ .../nifi/web/StandardNiFiServiceFacadeTest.java | 76 ++++++++++++++++++++++ .../apache/nifi/web/api/TestConnectorResource.java | 27 ++++++++ 10 files changed, 337 insertions(+) diff --git a/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/SecretDTO.java b/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/SecretDTO.java new file mode 100644 index 00000000000..fdcb972aae5 --- /dev/null +++ b/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/SecretDTO.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.nifi.web.api.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.xml.bind.annotation.XmlType; + +/** + * DTO representing a secret's metadata. Note: The actual secret value is never exposed via the REST API. + */ +@XmlType(name = "secret") +public class SecretDTO { + + private String providerName; + private String groupName; + private String name; + private String description; + + @Schema(description = "The name of the secret provider that manages this secret.") + public String getProviderName() { + return providerName; + } + + public void setProviderName(final String providerName) { + this.providerName = providerName; + } + + @Schema(description = "The name of the group this secret belongs to.") + public String getGroupName() { + return groupName; + } + + public void setGroupName(final String groupName) { + this.groupName = groupName; + } + + @Schema(description = "The name of the secret.") + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Schema(description = "A description of the secret.") + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } +} + diff --git a/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/SecretsEntity.java b/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/SecretsEntity.java new file mode 100644 index 00000000000..0706dde05c9 --- /dev/null +++ b/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/SecretsEntity.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.nifi.web.api.entity; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.xml.bind.annotation.XmlRootElement; +import org.apache.nifi.web.api.dto.SecretDTO; + +import java.util.List; + +/** + * A serialized representation of this class can be placed in the entity body of a response to the API. + * This particular entity holds a list of secrets. + */ +@XmlRootElement(name = "secretsEntity") +public class SecretsEntity extends Entity { + + private List<SecretDTO> secrets; + + @Schema(description = "The list of secrets available from all secret providers.") + public List<SecretDTO> getSecrets() { + return secrets; + } + + public void setSecrets(final List<SecretDTO> secrets) { + this.secrets = secrets; + } +} + diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java index aee15d1c45e..963ec8e401a 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java @@ -161,6 +161,7 @@ import org.apache.nifi.web.api.entity.StatusHistoryEntity; import org.apache.nifi.web.api.entity.TenantsEntity; import org.apache.nifi.web.api.entity.UserEntity; import org.apache.nifi.web.api.entity.UserGroupEntity; +import org.apache.nifi.web.api.entity.SecretsEntity; import org.apache.nifi.web.api.entity.VersionControlComponentMappingEntity; import org.apache.nifi.web.api.entity.VersionControlInformationEntity; import org.apache.nifi.web.api.entity.VersionedFlowEntity; @@ -3197,4 +3198,16 @@ public interface NiFiServiceFacade { * @return the list of listen Ports accessible to the current user */ Set<ListenPortDTO> getListenPorts(NiFiUser user); + + // ---------------------------------------- + // Secrets methods + // ---------------------------------------- + + /** + * Gets all secrets available from all secret providers. Note: The actual secret values are not included + * in the response for security reasons; only metadata is returned. + * + * @return the secrets entity containing metadata for all available secrets + */ + SecretsEntity getSecrets(); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java index df04e148d2b..2549c14350f 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java @@ -79,6 +79,8 @@ import org.apache.nifi.components.RequiredPermission; import org.apache.nifi.components.ValidationResult; import org.apache.nifi.components.Validator; import org.apache.nifi.components.connector.ConnectorNode; +import org.apache.nifi.components.connector.Secret; +import org.apache.nifi.components.connector.secrets.AuthorizableSecret; import org.apache.nifi.components.state.Scope; import org.apache.nifi.components.state.StateMap; import org.apache.nifi.components.validation.ValidationState; @@ -293,6 +295,7 @@ import org.apache.nifi.web.api.dto.ReportingTaskDTO; import org.apache.nifi.web.api.dto.RequiredPermissionDTO; import org.apache.nifi.web.api.dto.ResourceDTO; import org.apache.nifi.web.api.dto.RevisionDTO; +import org.apache.nifi.web.api.dto.SecretDTO; import org.apache.nifi.web.api.dto.SnippetDTO; import org.apache.nifi.web.api.dto.SystemDiagnosticsDTO; import org.apache.nifi.web.api.dto.TenantDTO; @@ -390,6 +393,7 @@ import org.apache.nifi.web.api.entity.ConnectorEntity; import org.apache.nifi.web.api.entity.ConfigurationStepEntity; import org.apache.nifi.web.api.entity.ConfigurationStepNamesEntity; import org.apache.nifi.web.api.entity.ScheduleComponentsEntity; +import org.apache.nifi.web.api.entity.SecretsEntity; import org.apache.nifi.web.api.entity.SnippetEntity; import org.apache.nifi.web.api.entity.StartVersionControlRequestEntity; import org.apache.nifi.web.api.entity.StatusHistoryEntity; @@ -7762,4 +7766,23 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { final ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId); return getComponents.apply(processGroup); } + + @Override + public SecretsEntity getSecrets() { + final NiFiUser user = NiFiUserUtils.getNiFiUser(); + final List<Secret> secrets = controllerFacade.getAllSecrets(); + final List<SecretDTO> secretDtos = secrets.stream() + .filter(secret -> isSecretAuthorized(secret, user)) + .map(dtoFactory::createSecretDto) + .toList(); + return entityFactory.createSecretsEntity(secretDtos); + } + + private boolean isSecretAuthorized(final Secret secret, final NiFiUser user) { + if (secret instanceof AuthorizableSecret authorizableSecret) { + final AuthorizationResult result = authorizableSecret.checkAuthorization(authorizer, RequestAction.READ, user); + return Result.Approved.equals(result.getResult()); + } + return true; + } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectorResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectorResource.java index ffc3fc264d8..e5ad85ea1a5 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectorResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectorResource.java @@ -65,6 +65,7 @@ import org.apache.nifi.web.api.entity.ConnectorRunStatusEntity; import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity; import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity; import org.apache.nifi.web.api.entity.SearchResultsEntity; +import org.apache.nifi.web.api.entity.SecretsEntity; import org.apache.nifi.web.api.concurrent.AsyncRequestManager; import org.apache.nifi.web.api.concurrent.AsynchronousWebRequest; import org.apache.nifi.web.api.concurrent.RequestManager; @@ -313,6 +314,53 @@ public class ConnectorResource extends ApplicationResource { return generateOkResponse(entity).build(); } + /** + * Gets all available secrets from the SecretsManager for configuring a specific connector. + * + * @param id The id of the connector being configured + * @return A secretsEntity containing metadata for all available secrets. + */ + @GET + @Consumes(MediaType.WILDCARD) + @Produces(MediaType.APPLICATION_JSON) + @Path("/{id}/secrets") + @Operation( + summary = "Gets all secrets available for configuring a connector", + description = "Returns metadata for all secrets available from all secret providers. " + + "This endpoint is used when configuring a connector to discover available secrets. " + + "Note: Actual secret values are not included in the response for security reasons.", + responses = { + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = SecretsEntity.class))), + @ApiResponse(responseCode = "400", description = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."), + @ApiResponse(responseCode = "401", description = "Client could not be authenticated."), + @ApiResponse(responseCode = "403", description = "Client is not authorized to make this request."), + @ApiResponse(responseCode = "404", description = "The specified resource could not be found."), + @ApiResponse(responseCode = "409", description = "The request was valid but NiFi was not in the appropriate state to process it.") + }, + security = { + @SecurityRequirement(name = "Write - /connectors/{uuid}") + } + ) + public Response getSecrets( + @Parameter( + description = "The connector id.", + required = true + ) + @PathParam("id") final String id) { + + // NOTE: fetching secrets is handled by the node that receives the request and does not need to be replicated + // Secrets are sourced from ParameterProviders which should have consistent configuration across the cluster + + // authorize access - require write permission on the specific connector since this is used for configuration + serviceFacade.authorizeAccess(lookup -> { + final Authorizable connector = lookup.getConnector(id); + connector.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser()); + }); + + final SecretsEntity entity = serviceFacade.getSecrets(); + return generateOkResponse(entity).build(); + } + /** * Updates the specified connector. * diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java index 17e3c4ed55f..1caede055e0 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java @@ -80,6 +80,7 @@ import org.apache.nifi.components.connector.ConnectorPropertyGroup; import org.apache.nifi.components.connector.ConnectorValueReference; import org.apache.nifi.components.connector.FrameworkFlowContext; import org.apache.nifi.components.connector.NamedStepConfiguration; +import org.apache.nifi.components.connector.Secret; import org.apache.nifi.components.connector.SecretReference; import org.apache.nifi.components.connector.StepConfiguration; import org.apache.nifi.components.connector.StringLiteralValue; @@ -5431,4 +5432,24 @@ public final class DtoFactory { return dto; } + /** + * Creates a SecretDTO from the specified Secret. Note: The secret value is intentionally not included + * in the DTO for security reasons. + * + * @param secret the secret + * @return the DTO containing only the secret's metadata + */ + public SecretDTO createSecretDto(final Secret secret) { + if (secret == null) { + return null; + } + + final SecretDTO dto = new SecretDTO(); + dto.setProviderName(secret.getProviderName()); + dto.setGroupName(secret.getGroupName()); + dto.setName(secret.getName()); + dto.setDescription(secret.getDescription()); + return dto; + } + } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java index cd748204af9..a8ca5ab8c34 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java @@ -83,6 +83,7 @@ import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity; import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity; import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity; import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusSnapshotEntity; +import org.apache.nifi.web.api.entity.SecretsEntity; import org.apache.nifi.web.api.entity.ReportingTaskEntity; import org.apache.nifi.web.api.entity.SnippetEntity; import org.apache.nifi.web.api.entity.StatusHistoryEntity; @@ -921,4 +922,10 @@ public final class EntityFactory { entity.setAllowableValues(allowableValues); return entity; } + + public SecretsEntity createSecretsEntity(final List<SecretDTO> secrets) { + final SecretsEntity entity = new SecretsEntity(); + entity.setSecrets(secrets); + return entity; + } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java index 7bc8615c8b3..b08a5097f4c 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java @@ -46,6 +46,7 @@ import org.apache.nifi.components.RequiredPermission; import org.apache.nifi.components.listen.ListenComponent; import org.apache.nifi.components.connector.Connector; import org.apache.nifi.components.connector.ConnectorNode; +import org.apache.nifi.components.connector.Secret; import org.apache.nifi.connectable.Connectable; import org.apache.nifi.connectable.Connection; import org.apache.nifi.connectable.Port; @@ -2000,6 +2001,15 @@ public class ControllerFacade implements Authorizable { return new StandardVersionedReportingTaskImporter(flowController); } + /** + * Gets all secrets from the SecretsManager. + * + * @return list of all secrets available from all secret providers + */ + public List<Secret> getAllSecrets() { + return flowController.getConnectorRepository().getSecretsManager().getAllSecrets(); + } + /* * setters */ diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/StandardNiFiServiceFacadeTest.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/StandardNiFiServiceFacadeTest.java index e3bd3f67dd1..65b16e4e697 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/StandardNiFiServiceFacadeTest.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/StandardNiFiServiceFacadeTest.java @@ -39,6 +39,8 @@ import org.apache.nifi.authorization.user.StandardNiFiUser.Builder; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.components.connector.ConnectorNode; import org.apache.nifi.components.connector.FrameworkFlowContext; +import org.apache.nifi.components.connector.Secret; +import org.apache.nifi.components.connector.secrets.AuthorizableSecret; import org.apache.nifi.controller.Counter; import org.apache.nifi.controller.FlowController; import org.apache.nifi.controller.ProcessorNode; @@ -105,6 +107,7 @@ import org.apache.nifi.web.api.entity.ClearBulletinsResultEntity; import org.apache.nifi.web.api.entity.ClearBulletinsForGroupResultsEntity; import org.apache.nifi.web.api.entity.CopyRequestEntity; import org.apache.nifi.web.api.entity.CopyResponseEntity; +import org.apache.nifi.web.api.entity.SecretsEntity; import org.apache.nifi.web.api.entity.ProcessGroupEntity; import org.apache.nifi.web.api.entity.StatusHistoryEntity; import org.apache.nifi.web.api.entity.TenantEntity; @@ -1700,4 +1703,77 @@ public class StandardNiFiServiceFacadeTest { serviceFacade.clearBulletinsForComponents(processGroupId, fromTimestamp, emptyComponentIds); }); } + + @Test + public void testGetSecretsFiltersUnauthorizedSecrets() { + final Authentication authentication = new NiFiAuthenticationToken(new NiFiUserDetails(new Builder().identity(USER_1).build())); + SecurityContextHolder.getContext().setAuthentication(authentication); + + final ControllerFacade controllerFacade = mock(ControllerFacade.class); + serviceFacade.setControllerFacade(controllerFacade); + + final AuthorizableSecret authorizedSecret = mock(AuthorizableSecret.class); + when(authorizedSecret.getProviderName()).thenReturn("provider1"); + when(authorizedSecret.getGroupName()).thenReturn("group1"); + when(authorizedSecret.getName()).thenReturn("authorized-secret"); + when(authorizedSecret.getDescription()).thenReturn("An authorized secret"); + when(authorizedSecret.checkAuthorization(any(Authorizer.class), any(), any())).thenReturn(AuthorizationResult.approved()); + + final AuthorizableSecret unauthorizedSecret = mock(AuthorizableSecret.class); + when(unauthorizedSecret.getProviderName()).thenReturn("provider2"); + when(unauthorizedSecret.getGroupName()).thenReturn("group2"); + when(unauthorizedSecret.getName()).thenReturn("unauthorized-secret"); + when(unauthorizedSecret.getDescription()).thenReturn("An unauthorized secret"); + when(unauthorizedSecret.checkAuthorization(any(Authorizer.class), any(), any())).thenReturn(AuthorizationResult.denied()); + + when(controllerFacade.getAllSecrets()).thenReturn(List.of(authorizedSecret, unauthorizedSecret)); + + final SecretsEntity result = serviceFacade.getSecrets(); + + assertNotNull(result); + assertNotNull(result.getSecrets()); + assertEquals(1, result.getSecrets().size()); + assertEquals("authorized-secret", result.getSecrets().get(0).getName()); + } + + @Test + public void testGetSecretsWithNonAuthorizableSecrets() { + final Authentication authentication = new NiFiAuthenticationToken(new NiFiUserDetails(new Builder().identity(USER_1).build())); + SecurityContextHolder.getContext().setAuthentication(authentication); + + final ControllerFacade controllerFacade = mock(ControllerFacade.class); + serviceFacade.setControllerFacade(controllerFacade); + + final Secret nonAuthorizableSecret = mock(Secret.class); + when(nonAuthorizableSecret.getProviderName()).thenReturn("provider1"); + when(nonAuthorizableSecret.getGroupName()).thenReturn("group1"); + when(nonAuthorizableSecret.getName()).thenReturn("non-authorizable-secret"); + when(nonAuthorizableSecret.getDescription()).thenReturn("A non-authorizable secret"); + + when(controllerFacade.getAllSecrets()).thenReturn(List.of(nonAuthorizableSecret)); + + final SecretsEntity result = serviceFacade.getSecrets(); + + assertNotNull(result); + assertNotNull(result.getSecrets()); + assertEquals(1, result.getSecrets().size()); + assertEquals("non-authorizable-secret", result.getSecrets().get(0).getName()); + } + + @Test + public void testGetSecretsWithEmptyList() { + final Authentication authentication = new NiFiAuthenticationToken(new NiFiUserDetails(new Builder().identity(USER_1).build())); + SecurityContextHolder.getContext().setAuthentication(authentication); + + final ControllerFacade controllerFacade = mock(ControllerFacade.class); + serviceFacade.setControllerFacade(controllerFacade); + + when(controllerFacade.getAllSecrets()).thenReturn(List.of()); + + final SecretsEntity result = serviceFacade.getSecrets(); + + assertNotNull(result); + assertNotNull(result.getSecrets()); + assertTrue(result.getSecrets().isEmpty()); + } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestConnectorResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestConnectorResource.java index e1093d266d9..df21a6935e3 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestConnectorResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestConnectorResource.java @@ -35,6 +35,7 @@ import org.apache.nifi.web.api.entity.AllowableValueEntity; import org.apache.nifi.web.api.entity.ConnectorEntity; import org.apache.nifi.web.api.entity.ConnectorPropertyAllowableValuesEntity; import org.apache.nifi.web.api.entity.ConnectorRunStatusEntity; +import org.apache.nifi.web.api.entity.SecretsEntity; import org.apache.nifi.web.api.request.ClientIdParameter; import org.apache.nifi.web.api.request.LongParameter; import org.junit.jupiter.api.BeforeEach; @@ -326,6 +327,32 @@ public class TestConnectorResource { verify(serviceFacade, never()).getConnectorPropertyAllowableValues(anyString(), anyString(), anyString(), anyString(), any()); } + @Test + public void testGetSecrets() { + final SecretsEntity responseEntity = new SecretsEntity(); + responseEntity.setSecrets(List.of()); + + when(serviceFacade.getSecrets()).thenReturn(responseEntity); + + try (Response response = connectorResource.getSecrets(CONNECTOR_ID)) { + assertEquals(200, response.getStatus()); + assertEquals(responseEntity, response.getEntity()); + } + + verify(serviceFacade).authorizeAccess(any(AuthorizeAccess.class)); + verify(serviceFacade).getSecrets(); + } + + @Test + public void testGetSecretsNotAuthorized() { + doThrow(AccessDeniedException.class).when(serviceFacade).authorizeAccess(any(AuthorizeAccess.class)); + + assertThrows(AccessDeniedException.class, () -> connectorResource.getSecrets(CONNECTOR_ID)); + + verify(serviceFacade).authorizeAccess(any(AuthorizeAccess.class)); + verify(serviceFacade, never()).getSecrets(); + } + private ConnectorEntity createConnectorEntity() { final ConnectorEntity entity = new ConnectorEntity();
