Fixes #10498 - Add support for nifi client certificate auth. (#10499)

* feat: Added nifi support for client cert auth

* feat: fix code linting

* feat: addressed comments for nifi connections

* feat: fixed linting
This commit is contained in:
Teddy 2023-03-10 11:09:40 +01:00 committed by GitHub
parent b94927b3ea
commit 7ec667808c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 109 additions and 30 deletions

View File

@ -32,19 +32,40 @@ class NifiClient:
Wrapper on top of Nifi REST API Wrapper on top of Nifi REST API
""" """
# pylint: disable=too-many-arguments
def __init__( def __init__(
self, host_port: str, username: str, password: str, verify: bool = False self,
host_port: str,
username: Optional[str] = None,
password: Optional[str] = None,
ca_file_path: Optional[str] = None,
client_cert_path: Optional[str] = None,
client_key_path: Optional[str] = None,
verify: bool = False,
): ):
self._token = None self._token = None
self._resources = None self._resources = None
self.content_headers = {"Content-Type": "application/x-www-form-urlencoded"}
self.api_endpoint = host_port + "/nifi-api"
self.username = username self.username = username
self.password = password self.password = password
self.verify = verify
self.api_endpoint = host_port + "/nifi-api"
self.content_headers = {"Content-Type": "application/x-www-form-urlencoded"} if all(setting for setting in [self.username, self.password]):
self.headers = {"Authorization": f"Bearer {self.token}", **self.content_headers} self.verify = verify
self.headers = {
"Authorization": f"Bearer {self.token}",
**self.content_headers,
}
self.data = f"username={self.username}&password={self.password}"
self.client_cert = None
else:
self.data = None
self.verify = ca_file_path if ca_file_path else False
self.client_cert = (client_cert_path, client_key_path)
self.headers = self.content_headers
access = self.get("access")
logger.debug(access)
@property @property
def token(self) -> str: def token(self) -> str:
@ -58,7 +79,7 @@ class NifiClient:
f"{self.api_endpoint}/access/token", f"{self.api_endpoint}/access/token",
verify=self.verify, verify=self.verify,
headers=self.content_headers, headers=self.content_headers,
data=f"username={self.username}&password={self.password}", data=self.data,
timeout=REQUESTS_TIMEOUT, timeout=REQUESTS_TIMEOUT,
) )
self._token = res.text self._token = res.text
@ -84,7 +105,10 @@ class NifiClient:
self._resources = self.get(RESOURCES) # API endpoint self._resources = self.get(RESOURCES) # API endpoint
# Get the first `resources` key from the dict # Get the first `resources` key from the dict
return self._resources.get(RESOURCES) # Dict key try:
return self._resources.get(RESOURCES) # Dict key
except AttributeError:
return []
def get(self, path: str) -> Optional[Any]: def get(self, path: str) -> Optional[Any]:
""" """
@ -96,6 +120,7 @@ class NifiClient:
verify=self.verify, verify=self.verify,
headers=self.headers, headers=self.headers,
timeout=REQUESTS_TIMEOUT, timeout=REQUESTS_TIMEOUT,
cert=self.client_cert,
) )
return res.json() return res.json()

View File

@ -13,6 +13,7 @@
Source connection handler Source connection handler
""" """
from metadata.generated.schema.entity.services.connections.pipeline.nifiConnection import ( from metadata.generated.schema.entity.services.connections.pipeline.nifiConnection import (
BasicAuthentication,
NifiConnection, NifiConnection,
) )
from metadata.ingestion.connections.test_connections import SourceConnectionException from metadata.ingestion.connections.test_connections import SourceConnectionException
@ -23,11 +24,21 @@ def get_connection(connection: NifiConnection) -> NifiClient:
""" """
Create connection Create connection
""" """
if isinstance(connection.nifiConfig, BasicAuthentication):
return NifiClient(
host_port=connection.hostPort,
username=connection.nifiConfig.username,
password=connection.nifiConfig.password.get_secret_value()
if connection.nifiConfig.password
else None,
verify=connection.nifiConfig.verifySSL,
)
return NifiClient( return NifiClient(
host_port=connection.hostPort, host_port=connection.hostPort,
username=connection.username, ca_file_path=connection.nifiConfig.certificateAuthorityPath,
password=connection.password.get_secret_value(), client_cert_path=connection.nifiConfig.clientCertificatePath,
verify=connection.verifySSL, client_key_path=connection.nifiConfig.clientkeyPath,
) )

View File

@ -55,9 +55,11 @@ mock_nifi_config = {
"config": { "config": {
"type": "Nifi", "type": "Nifi",
"hostPort": "https://localhost:8443", "hostPort": "https://localhost:8443",
"username": "username", "nifiConfig": {
"password": "password", "username": "username",
"verifySSL": False, "password": "password",
"verifySSL": False,
},
} }
}, },
"sourceConfig": {"config": {"type": "PipelineMetadata"}}, "sourceConfig": {"config": {"type": "PipelineMetadata"}},

View File

@ -11,6 +11,52 @@
"type": "string", "type": "string",
"enum": ["Nifi"], "enum": ["Nifi"],
"default": "Nifi" "default": "Nifi"
},
"basicAuthentication": {
"title": "Username/Password Authentication",
"description": "username/password auth",
"properties": {
"username": {
"title": "Username",
"description": "Nifi user to authenticate to the API.",
"type": "string"
},
"password": {
"title": "Password",
"description": "Nifi password to authenticate to the API.",
"type": "string",
"format": "password"
},
"verifySSL": {
"title": "Verify SSL",
"description": "Boolean marking if we need to verify the SSL certs for Nifi. False by default.",
"type": "boolean",
"default": false
}
},
"additionalProperties": false
},
"clientCertificateAuthentication": {
"title": "Client Certificate Authentication",
"description": "client certificate auth",
"properties": {
"certificateAuthorityPath":{
"title":"Certificat Authority Path",
"description": "Path to the root CA certificate",
"type": "string"
},
"clientCertificatePath":{
"title":"Client Certificat",
"description": "Path to the client certificate",
"type": "string"
},
"clientkeyPath":{
"title":"Client Key",
"description": "Path to the client key",
"type": "string"
}
},
"additionalProperties": false
} }
}, },
"properties": { "properties": {
@ -27,22 +73,17 @@
"type": "string", "type": "string",
"format": "uri" "format": "uri"
}, },
"username": { "nifiConfig": {
"title": "Username", "title": "Nifi Credentials Configuration",
"description": "Nifi user to authenticate to the API.", "description": "We support username/password or client certificate authentication",
"type": "string" "oneOf": [
}, {
"password": { "$ref": "#/definitions/basicAuthentication"
"title": "Password", },
"description": "Nifi password to authenticate to the API.", {
"type": "string", "$ref": "#/definitions/clientCertificateAuthentication"
"format": "password" }
}, ]
"verifySSL": {
"title": "Verify SSL",
"description": "Boolean marking if we need to verify the SSL certs for Nifi. False by default.",
"type": "boolean",
"default": false
}, },
"supportsMetadataExtraction": { "supportsMetadataExtraction": {
"title": "Supports Metadata Extraction", "title": "Supports Metadata Extraction",
@ -50,5 +91,5 @@
} }
}, },
"additionalProperties": false, "additionalProperties": false,
"required": ["hostPort", "username", "password"] "required": ["hostPort", "nifiConfig"]
} }