Fixes 11068: mysql & postgres iam auth (#11937)

This commit is contained in:
Ayush Shah 2023-06-16 13:18:12 +05:30 committed by GitHub
parent 8ad8001da1
commit f80eaf3a26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 657 additions and 104 deletions

View File

@ -109,3 +109,15 @@ SET pe.json = JSON_INSERT(
'$.tasks', '$.tasks',
updated_data.updated_json updated_data.updated_json
); );
-- Modify migrations for service connection of postgres and mysql to move password under authType
UPDATE dbservice_entity
SET json = JSON_INSERT(
JSON_REMOVE(json, '$.connection.config.password'),
'$.connection.config.authType',
JSON_OBJECT(),
'$.connection.config.authType.password',
JSON_EXTRACT(json, '$.connection.config.password'))
where serviceType in ('Postgres', 'Mysql');

View File

@ -72,3 +72,15 @@ SET json = jsonb_set(
FROM jsonb_array_elements(json->'tasks') AS t FROM jsonb_array_elements(json->'tasks') AS t
) )
); );
-- Modify migrations for service connection of postgres and mysql to move password under authType
UPDATE dbservice_entity
SET json = jsonb_set(
json #-'{connection,config,password}',
'{connection,config,authType}',
jsonb_build_object('password',json#>'{connection,config,password}')
)
WHERE serviceType IN ('Postgres', 'Mysql')
and json#>'{connection,config,password}' is not null;

View File

@ -34,6 +34,7 @@ class AWSServices(Enum):
KINESIS = "kinesis" KINESIS = "kinesis"
QUICKSIGHT = "quicksight" QUICKSIGHT = "quicksight"
ATHENA = "athena" ATHENA = "athena"
RDS = "rds"
class AWSAssumeRoleException(Exception): class AWSAssumeRoleException(Exception):
@ -162,6 +163,9 @@ class AWSClient:
) )
return session.resource(service_name=service_name) return session.resource(service_name=service_name)
def get_rds_client(self):
return self.get_client(AWSServices.RDS.value)
def get_s3_client(self): def get_s3_client(self):
return self.get_client(AWSServices.S3.value) return self.get_client(AWSServices.S3.value)

View File

@ -22,12 +22,17 @@ from sqlalchemy.engine import Engine
from sqlalchemy.event import listen from sqlalchemy.event import listen
from sqlalchemy.pool import QueuePool from sqlalchemy.pool import QueuePool
from metadata.clients.aws_client import AWSClient
from metadata.generated.schema.entity.services.connections.connectionBasicType import ( from metadata.generated.schema.entity.services.connections.connectionBasicType import (
ConnectionArguments, ConnectionArguments,
ConnectionOptions, ConnectionOptions,
) )
from metadata.generated.schema.entity.services.connections.database.common.iamAuthConfig import (
IamAuthConfigurationSource,
)
from metadata.ingestion.connections.headers import inject_query_header_by_conn from metadata.ingestion.connections.headers import inject_query_header_by_conn
from metadata.ingestion.connections.secrets import connection_with_options_secrets from metadata.ingestion.connections.secrets import connection_with_options_secrets
from metadata.utils.constants import BUILDER_PASSWORD_ATTR
@connection_with_options_secrets @connection_with_options_secrets
@ -117,6 +122,40 @@ def init_empty_connection_options() -> ConnectionOptions:
return ConnectionOptions(__root__={}) return ConnectionOptions(__root__={})
def _add_password(url: str, connection) -> str:
"""
A helper function that adds the password to the url if it exists.
Distinguishing between BasicAuth (Password) and IamAuth (AWSConfig)
and adding to url.
"""
password = getattr(connection, BUILDER_PASSWORD_ATTR, None)
if not password:
password = SecretStr("")
# Check if IamAuth exists - specific to Mysql and Postgres connection.
if hasattr(connection, "authType"):
password = getattr(
connection.authType, BUILDER_PASSWORD_ATTR, SecretStr("")
)
if isinstance(connection.authType, IamAuthConfigurationSource):
# if IAM based, fetch rds client and generate db auth token.
aws_client = AWSClient(
config=connection.authType.awsConfig
).get_rds_client()
host, port = connection.hostPort.split(":")
password = SecretStr(
aws_client.generate_db_auth_token(
DBHostname=host,
Port=port,
DBUsername=connection.username,
Region=connection.authType.awsConfig.awsRegion,
)
)
url += f":{quote_plus(password.get_secret_value())}"
return url
def get_connection_url_common(connection) -> str: def get_connection_url_common(connection) -> str:
""" """
Common method for building the source connection urls Common method for building the source connection urls
@ -126,9 +165,7 @@ def get_connection_url_common(connection) -> str:
if connection.username: if connection.username:
url += f"{quote_plus(connection.username)}" url += f"{quote_plus(connection.username)}"
if not connection.password: url = _add_password(url, connection)
connection.password = SecretStr("")
url += f":{quote_plus(connection.password.get_secret_value())}"
url += "@" url += "@"
url += connection.hostPort url += connection.hostPort

View File

@ -18,7 +18,7 @@ TEN_MIN = 10 * 60
UTF_8 = "utf-8" UTF_8 = "utf-8"
CHUNKSIZE = 200000 CHUNKSIZE = 200000
DEFAULT_DATABASE = "default" DEFAULT_DATABASE = "default"
BUILDER_PASSWORD_ATTR = "password"
ES_SOURCE_TO_ES_OBJ_ARGS = { ES_SOURCE_TO_ES_OBJ_ARGS = {
"caCerts": "ca_certs", "caCerts": "ca_certs",

View File

@ -5,7 +5,8 @@ source:
config: config:
type: Mysql type: Mysql
username: openmetadata_user username: openmetadata_user
password: openmetadata_password authType:
password: openmetadata_password
hostPort: localhost:3306 hostPort: localhost:3306
databaseSchema: openmetadata_db databaseSchema: openmetadata_db
connectionOptions: {} connectionOptions: {}

View File

@ -28,6 +28,9 @@ from metadata.generated.schema.entity.automations.workflow import (
WorkflowType, WorkflowType,
) )
from metadata.generated.schema.entity.data.pipeline import StatusType from metadata.generated.schema.entity.data.pipeline import StatusType
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
MySQLType, MySQLType,
@ -45,7 +48,7 @@ from metadata.ingestion.source.connections import get_connection, get_test_conne
SERVICE_CONNECTION = MysqlConnection( SERVICE_CONNECTION = MysqlConnection(
username="openmetadata_user", username="openmetadata_user",
password="openmetadata_password", authType=BasicAuth(password="openmetadata_password"),
hostPort="localhost:3306", hostPort="localhost:3306",
) )

View File

@ -16,6 +16,9 @@ from unittest import TestCase
from sqlalchemy.engine import Engine from sqlalchemy.engine import Engine
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -29,7 +32,7 @@ class MySQLConnectionTest(TestCase):
connection = MysqlConnection( connection = MysqlConnection(
username="openmetadata_user", username="openmetadata_user",
password="openmetadata_password", authType=BasicAuth(password="openmetadata_password"),
hostPort="localhost:3306", hostPort="localhost:3306",
databaseSchema="openmetadata_db", databaseSchema="openmetadata_db",
) )

View File

@ -35,6 +35,9 @@ from metadata.generated.schema.api.services.createDatabaseService import (
) )
from metadata.generated.schema.entity.data.pipeline import Pipeline, StatusType from metadata.generated.schema.entity.data.pipeline import Pipeline, StatusType
from metadata.generated.schema.entity.data.table import Column, DataType, Table from metadata.generated.schema.entity.data.table import Column, DataType, Table
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -100,7 +103,7 @@ class AirflowLineageTest(TestCase):
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(password="password"),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
), ),

View File

@ -21,6 +21,9 @@ from metadata.generated.schema.api.services.createDatabaseService import (
) )
from metadata.generated.schema.api.teams.createUser import CreateUserRequest from metadata.generated.schema.api.teams.createUser import CreateUserRequest
from metadata.generated.schema.entity.data.database import Database from metadata.generated.schema.entity.data.database import Database
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -69,7 +72,9 @@ class OMetaDatabaseTest(TestCase):
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
), ),

View File

@ -19,6 +19,9 @@ from metadata.generated.schema.api.services.createDatabaseService import (
CreateDatabaseServiceRequest, CreateDatabaseServiceRequest,
) )
from metadata.generated.schema.entity.data.database import Database from metadata.generated.schema.entity.data.database import Database
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -55,7 +58,11 @@ class OMetaDatabaseServiceTest(TestCase):
connection = DatabaseConnection( connection = DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", password="password", hostPort="http://localhost:1234" username="username",
authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234",
) )
) )
@ -119,7 +126,9 @@ class OMetaDatabaseServiceTest(TestCase):
new_connection = DatabaseConnection( new_connection = DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:2000", hostPort="http://localhost:2000",
) )
) )

View File

@ -24,6 +24,9 @@ from metadata.generated.schema.api.services.createDatabaseService import (
CreateDatabaseServiceRequest, CreateDatabaseServiceRequest,
) )
from metadata.generated.schema.entity.data.table import Column, DataType, Table from metadata.generated.schema.entity.data.table import Column, DataType, Table
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -65,7 +68,9 @@ class OMetaESTest(TestCase):
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
), ),

View File

@ -28,6 +28,9 @@ from metadata.generated.schema.api.services.createPipelineService import (
CreatePipelineServiceRequest, CreatePipelineServiceRequest,
) )
from metadata.generated.schema.entity.data.table import Column, DataType from metadata.generated.schema.entity.data.table import Column, DataType
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -84,7 +87,9 @@ class OMetaLineageTest(TestCase):
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
), ),

View File

@ -37,6 +37,9 @@ from metadata.generated.schema.entity.data.mlmodel import (
MlModel, MlModel,
) )
from metadata.generated.schema.entity.data.table import Column, DataType, Table from metadata.generated.schema.entity.data.table import Column, DataType, Table
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -270,7 +273,9 @@ class OMetaModelTest(TestCase):
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
), ),

View File

@ -29,6 +29,9 @@ from metadata.generated.schema.api.teams.createUser import CreateUserRequest
from metadata.generated.schema.entity.data.database import Database from metadata.generated.schema.entity.data.database import Database
from metadata.generated.schema.entity.data.databaseSchema import DatabaseSchema from metadata.generated.schema.entity.data.databaseSchema import DatabaseSchema
from metadata.generated.schema.entity.data.table import Column, DataType, Table from metadata.generated.schema.entity.data.table import Column, DataType, Table
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -106,7 +109,9 @@ class OMetaTableTest(TestCase):
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
), ),

View File

@ -79,7 +79,7 @@ class OMetaServiceTest(TestCase):
"config": { "config": {
"type": "Mysql", "type": "Mysql",
"username": "openmetadata_user", "username": "openmetadata_user",
"password": "openmetadata_password", "authType": {"password": "openmetadata_password"},
"hostPort": "random:3306", "hostPort": "random:3306",
} }
}, },
@ -95,7 +95,7 @@ class OMetaServiceTest(TestCase):
assert service assert service
assert service.serviceType == DatabaseServiceType.Mysql assert service.serviceType == DatabaseServiceType.Mysql
assert ( assert (
service.connection.config.password.get_secret_value() service.connection.config.authType.password.get_secret_value()
== "openmetadata_password" == "openmetadata_password"
) )

View File

@ -45,6 +45,9 @@ from metadata.generated.schema.entity.data.table import (
TableProfile, TableProfile,
TableProfilerConfig, TableProfilerConfig,
) )
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -97,7 +100,9 @@ class OMetaTableTest(TestCase):
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
), ),

View File

@ -26,6 +26,9 @@ from metadata.generated.schema.entity.automations.workflow import (
WorkflowStatus, WorkflowStatus,
WorkflowType, WorkflowType,
) )
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
MySQLType, MySQLType,
@ -88,7 +91,9 @@ class OMetaWorkflowTest(TestCase):
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
), ),
@ -108,7 +113,9 @@ class OMetaWorkflowTest(TestCase):
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
), ),
@ -156,7 +163,8 @@ class OMetaWorkflowTest(TestCase):
# The ingestion-bot should see the password # The ingestion-bot should see the password
self.assertEqual( self.assertEqual(
res.request.connection.config.password.get_secret_value(), "password" res.request.connection.config.authType.password.get_secret_value(),
"password",
) )
def test_get_id(self): def test_get_id(self):

View File

@ -25,6 +25,9 @@ from metadata.generated.schema.api.services.createDatabaseService import (
CreateDatabaseServiceRequest, CreateDatabaseServiceRequest,
) )
from metadata.generated.schema.entity.data.table import Column, DataType from metadata.generated.schema.entity.data.table import Column, DataType
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -71,7 +74,9 @@ class ProfilerWorkflowTest(TestCase):
connection = DatabaseConnection( connection = DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
) )

View File

@ -30,6 +30,9 @@ from metadata.generated.schema.entity.data.table import (
Table, Table,
TableData, TableData,
) )
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -286,7 +289,9 @@ class PiiProcessorTest(TestCase):
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
), ),

View File

@ -23,6 +23,9 @@ from metadata.generated.schema.api.services.createDatabaseService import (
CreateDatabaseServiceRequest, CreateDatabaseServiceRequest,
) )
from metadata.generated.schema.entity.data.table import Column, DataType, Table from metadata.generated.schema.entity.data.table import Column, DataType, Table
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -65,7 +68,9 @@ class FQNBuildTest(TestCase):
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
), ),

View File

@ -7,7 +7,9 @@
"type": "Mysql", "type": "Mysql",
"username": "openmetadata_user", "username": "openmetadata_user",
"database":"openmetadata_db", "database":"openmetadata_db",
"password": "openmetadata_password", "authType":{
"password": "openmetadata_password"
},
"hostPort": "localhost:3306", "hostPort": "localhost:3306",
"connectionOptions": {}, "connectionOptions": {},
"connectionArguments": {} "connectionArguments": {}

View File

@ -525,7 +525,7 @@ def test_mysql():
"config": { "config": {
"type": "Mysql", "type": "Mysql",
"username": "openmetadata_user", "username": "openmetadata_user",
"password": "openmetadata_password", "authType": {"password": "openmetadata_password"},
"hostPort": "localhost:3306", "hostPort": "localhost:3306",
} }
}, },

View File

@ -13,6 +13,9 @@ Validate connection builder utilities
""" """
from unittest import TestCase from unittest import TestCase
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -29,19 +32,21 @@ class ConnectionBuilderTest(TestCase):
""" """
connection = MysqlConnection( connection = MysqlConnection(
username="username", password="password", hostPort="http://localhost:1234" username="username",
authType=BasicAuth(password="password"),
hostPort="http://localhost:1234",
) )
connection_with_args = MysqlConnection( connection_with_args = MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(password="password"),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
connectionArguments={"hello": "world"}, connectionArguments={"hello": "world"},
) )
connection_with_options = MysqlConnection( connection_with_options = MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(password="password"),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
connectionOptions={"hello": "world"}, connectionOptions={"hello": "world"},
) )

View File

@ -19,6 +19,9 @@ from metadata.generated.schema.entity.services.connections.database.clickhouseCo
ClickhouseConnection, ClickhouseConnection,
ClickhouseScheme, ClickhouseScheme,
) )
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.databricksConnection import ( from metadata.generated.schema.entity.services.connections.database.databricksConnection import (
DatabricksConnection, DatabricksConnection,
DatabricksScheme, DatabricksScheme,
@ -36,7 +39,6 @@ from metadata.generated.schema.entity.services.connections.database.hiveConnecti
HiveScheme, HiveScheme,
) )
from metadata.generated.schema.entity.services.connections.database.impalaConnection import ( from metadata.generated.schema.entity.services.connections.database.impalaConnection import (
AuthMechanism,
ImpalaConnection, ImpalaConnection,
ImpalaScheme, ImpalaScheme,
) )
@ -654,8 +656,8 @@ class SourceConnectionTest(TestCase):
postgres_conn_obj = PostgresConnection( postgres_conn_obj = PostgresConnection(
username="openmetadata_user", username="openmetadata_user",
hostPort="localhost:5432", hostPort="localhost:5432",
scheme=PostgresScheme.postgresql_psycopg2,
database="default", database="default",
scheme=PostgresScheme.postgresql_psycopg2,
) )
assert expected_url == get_connection_url_common(postgres_conn_obj) assert expected_url == get_connection_url_common(postgres_conn_obj)
@ -753,7 +755,9 @@ class SourceConnectionTest(TestCase):
expected_args = {} expected_args = {}
mysql_conn_obj = MysqlConnection( mysql_conn_obj = MysqlConnection(
username="user", username="user",
password=None, authType=BasicAuth(
password=None,
),
hostPort="localhost:443", hostPort="localhost:443",
connectionArguments=None, connectionArguments=None,
scheme=MySQLScheme.mysql_pymysql, scheme=MySQLScheme.mysql_pymysql,
@ -764,7 +768,9 @@ class SourceConnectionTest(TestCase):
expected_args = {"user": "user-to-be-impersonated"} expected_args = {"user": "user-to-be-impersonated"}
mysql_conn_obj = MysqlConnection( mysql_conn_obj = MysqlConnection(
username="user", username="user",
password=None, authType=BasicAuth(
password=None,
),
hostPort="localhost:443", hostPort="localhost:443",
connectionArguments={"user": "user-to-be-impersonated"}, connectionArguments={"user": "user-to-be-impersonated"},
scheme=MySQLScheme.mysql_pymysql, scheme=MySQLScheme.mysql_pymysql,
@ -824,9 +830,11 @@ class SourceConnectionTest(TestCase):
expected_args = {} expected_args = {}
postgres_conn_obj = PostgresConnection( postgres_conn_obj = PostgresConnection(
username="user", username="user",
password=None, authType=BasicAuth(
hostPort="localhost:443", password=None,
),
database="postgres", database="postgres",
hostPort="localhost:443",
connectionArguments=None, connectionArguments=None,
scheme=PostgresScheme.postgresql_psycopg2, scheme=PostgresScheme.postgresql_psycopg2,
) )
@ -835,8 +843,10 @@ class SourceConnectionTest(TestCase):
# connection arguments with connectionArguments # connection arguments with connectionArguments
expected_args = {"user": "user-to-be-impersonated"} expected_args = {"user": "user-to-be-impersonated"}
postgres_conn_obj = PostgresConnection( postgres_conn_obj = PostgresConnection(
authType=BasicAuth(
password=None,
),
username="user", username="user",
password=None,
hostPort="localhost:443", hostPort="localhost:443",
database="tiny", database="tiny",
connectionArguments={"user": "user-to-be-impersonated"}, connectionArguments={"user": "user-to-be-impersonated"},

View File

@ -14,6 +14,9 @@ OpenMetadata source URL building tests
""" """
from unittest import TestCase from unittest import TestCase
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mssqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mssqlConnection import (
MssqlConnection, MssqlConnection,
MssqlScheme, MssqlScheme,
@ -34,7 +37,7 @@ class TestConfig(TestCase):
""" """
connection = MysqlConnection( connection = MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(password="password"),
hostPort="localhost:1234", hostPort="localhost:1234",
) )
url = get_connection_url_common(connection) url = get_connection_url_common(connection)

View File

@ -320,7 +320,7 @@ class TestWorkflowParse(TestCase):
"config": { "config": {
"type": "Mysql", "type": "Mysql",
"username": "openmetadata_user", "username": "openmetadata_user",
"password": "openmetadata_password", "authType": {"password": "openmetadata_password"},
"hostPort": "localhost:3306", "hostPort": "localhost:3306",
} }
}, },
@ -337,7 +337,7 @@ class TestWorkflowParse(TestCase):
"config": { "config": {
"type": "Mysql", "type": "Mysql",
"username": "openmetadata_user", "username": "openmetadata_user",
"password": "openmetadata_password", "authType": {"password": "openmetadata_password"},
} }
}, },
"connectionType": "Database", "connectionType": "Database",
@ -355,7 +355,7 @@ class TestWorkflowParse(TestCase):
"config": { "config": {
"type": "Mysql", "type": "Mysql",
"username": "openmetadata_user", "username": "openmetadata_user",
"password": "openmetadata_password", "authType": {"password": "openmetadata_password"},
"hostPort": "localhost:3306", "hostPort": "localhost:3306",
"random": "value", "random": "value",
} }

View File

@ -155,7 +155,7 @@ class LookerUnitTest(TestCase):
"config": { "config": {
"type": "Mysql", "type": "Mysql",
"username": "openmetadata_user", "username": "openmetadata_user",
"password": "openmetadata_password", "authType": {"password": "openmetadata_password"},
"hostPort": "localhost:3306", "hostPort": "localhost:3306",
"databaseSchema": "openmetadata_db", "databaseSchema": "openmetadata_db",
} }

View File

@ -23,6 +23,9 @@ from sqlalchemy.engine import Engine
from metadata.generated.schema.api.data.createChart import CreateChartRequest from metadata.generated.schema.api.data.createChart import CreateChartRequest
from metadata.generated.schema.api.data.createDashboard import CreateDashboardRequest from metadata.generated.schema.api.data.createDashboard import CreateDashboardRequest
from metadata.generated.schema.entity.data.chart import Chart, ChartType from metadata.generated.schema.entity.data.chart import Chart, ChartType
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -110,7 +113,9 @@ MOCK_SUPERSET_DB_CONFIG = {
"connection": { "connection": {
"type": "Postgres", "type": "Postgres",
"username": "superset", "username": "superset",
"password": "superset", "authType": {
"password": "superset",
},
"hostPort": "localhost:5432", "hostPort": "localhost:5432",
"database": "superset", "database": "superset",
}, },
@ -147,7 +152,9 @@ MOCK_DB_MYSQL_SERVICE_1 = DatabaseService(
name="test_mysql", name="test_mysql",
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="user", password="pass", hostPort="localhost:3306" username="user",
authType=BasicAuth(password="pass"),
hostPort="localhost:3306",
) )
), ),
serviceType=DatabaseServiceType.Mysql, serviceType=DatabaseServiceType.Mysql,
@ -160,7 +167,7 @@ MOCK_DB_MYSQL_SERVICE_2 = DatabaseService(
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="user", username="user",
password="pass", authType=BasicAuth(password="pass"),
hostPort="localhost:3306", hostPort="localhost:3306",
databaseName="DUMMY_DB", databaseName="DUMMY_DB",
) )
@ -175,7 +182,7 @@ MOCK_DB_POSTGRES_SERVICE = DatabaseService(
connection=DatabaseConnection( connection=DatabaseConnection(
config=PostgresConnection( config=PostgresConnection(
username="user", username="user",
password="pass", authType=BasicAuth(password="pass"),
hostPort="localhost:5432", hostPort="localhost:5432",
database="postgres", database="postgres",
) )
@ -282,7 +289,9 @@ class SupersetUnitTest(TestCase):
"config": { "config": {
"type": "Mysql", "type": "Mysql",
"username": "openmetadata_user", "username": "openmetadata_user",
"password": "openmetadata_password", "authType": {
"password": "openmetadata_password",
},
"hostPort": "localhost:3306", "hostPort": "localhost:3306",
"databaseSchema": "openmetadata_db", "databaseSchema": "openmetadata_db",
} }

View File

@ -50,7 +50,9 @@ mock_postgres_config = {
"config": { "config": {
"type": "Postgres", "type": "Postgres",
"username": "username", "username": "username",
"password": "password", "authType": {
"password": "password",
},
"hostPort": "localhost:5432", "hostPort": "localhost:5432",
"database": "postgres", "database": "postgres",
} }
@ -84,7 +86,9 @@ mock_postgres_usage_config = {
"config": { "config": {
"type": "Postgres", "type": "Postgres",
"username": "username", "username": "username",
"password": "password", "authType": {
"password": "password",
},
"hostPort": "localhost:5432", "hostPort": "localhost:5432",
"database": "postgres", "database": "postgres",
} }

View File

@ -126,7 +126,7 @@ class StorageUnitTest(TestCase):
"config": { "config": {
"type": "Mysql", "type": "Mysql",
"username": "openmetadata_user", "username": "openmetadata_user",
"password": "openmetadata_password", "authType": {"password": "openmetadata_password"},
"hostPort": "localhost:3306", "hostPort": "localhost:3306",
"databaseSchema": "openmetadata_db", "databaseSchema": "openmetadata_db",
} }

View File

@ -14,7 +14,9 @@
"type": "MySQL", "type": "MySQL",
"scheme": "mysql+pymysql", "scheme": "mysql+pymysql",
"username": "openmetadata_user", "username": "openmetadata_user",
"password": "openmetadata_password", "authType":{
"password": "openmetadata_password"
},
"hostPort": "localhost:3306", "hostPort": "localhost:3306",
"database": null, "database": null,
"connectionOptions": null, "connectionOptions": null,

View File

@ -3,7 +3,9 @@
"config": { "config": {
"type": "MySQL", "type": "MySQL",
"username": "openmetadata_user", "username": "openmetadata_user",
"password": "openmetadata_password", "authType":{
"password": "openmetadata_password"
},
"hostPort": "localhost:3306" "hostPort": "localhost:3306"
} }
} }

View File

@ -24,6 +24,9 @@ from unittest import TestCase
from metadata.generated.schema.api.services.createDatabaseService import ( from metadata.generated.schema.api.services.createDatabaseService import (
CreateDatabaseServiceRequest, CreateDatabaseServiceRequest,
) )
from metadata.generated.schema.entity.services.connections.database.common.basicAuth import (
BasicAuth,
)
from metadata.generated.schema.entity.services.connections.database.mysqlConnection import ( from metadata.generated.schema.entity.services.connections.database.mysqlConnection import (
MysqlConnection, MysqlConnection,
) )
@ -216,7 +219,9 @@ class TestAirflowOps(TestCase):
connection=DatabaseConnection( connection=DatabaseConnection(
config=MysqlConnection( config=MysqlConnection(
username="username", username="username",
password="password", authType=BasicAuth(
password="password",
),
hostPort="http://localhost:1234", hostPort="http://localhost:1234",
) )
), ),

View File

@ -105,7 +105,7 @@ class OMetaServiceTest(TestCase):
"config": { "config": {
"type": "Mysql", "type": "Mysql",
"username": "openmetadata_user", "username": "openmetadata_user",
"password": "openmetadata_password", "authType": {"password": "openmetadata_password"},
"hostPort": "localhost:3306", "hostPort": "localhost:3306",
} }
}, },

View File

@ -26,6 +26,8 @@ import org.openmetadata.schema.services.connections.dashboard.SupersetConnection
import org.openmetadata.schema.services.connections.dashboard.TableauConnection; import org.openmetadata.schema.services.connections.dashboard.TableauConnection;
import org.openmetadata.schema.services.connections.database.BigQueryConnection; import org.openmetadata.schema.services.connections.database.BigQueryConnection;
import org.openmetadata.schema.services.connections.database.DatalakeConnection; import org.openmetadata.schema.services.connections.database.DatalakeConnection;
import org.openmetadata.schema.services.connections.database.MysqlConnection;
import org.openmetadata.schema.services.connections.database.PostgresConnection;
import org.openmetadata.schema.services.connections.database.datalake.GCSConfig; import org.openmetadata.schema.services.connections.database.datalake.GCSConfig;
import org.openmetadata.schema.services.connections.metadata.OpenMetadataConnection; import org.openmetadata.schema.services.connections.metadata.OpenMetadataConnection;
import org.openmetadata.schema.services.connections.pipeline.AirflowConnection; import org.openmetadata.schema.services.connections.pipeline.AirflowConnection;
@ -45,6 +47,8 @@ public final class ClassConverterFactory {
Map.entry(AirflowConnection.class, new AirflowConnectionClassConverter()), Map.entry(AirflowConnection.class, new AirflowConnectionClassConverter()),
Map.entry(BigQueryConnection.class, new BigQueryConnectionClassConverter()), Map.entry(BigQueryConnection.class, new BigQueryConnectionClassConverter()),
Map.entry(DatalakeConnection.class, new DatalakeConnectionClassConverter()), Map.entry(DatalakeConnection.class, new DatalakeConnectionClassConverter()),
Map.entry(MysqlConnection.class, new MysqlConnectionClassConverter()),
Map.entry(PostgresConnection.class, new PostgresConnectionClassConverter()),
Map.entry(DbtGCSConfig.class, new DbtGCSConfigClassConverter()), Map.entry(DbtGCSConfig.class, new DbtGCSConfigClassConverter()),
Map.entry(DbtPipeline.class, new DbtPipelineClassConverter()), Map.entry(DbtPipeline.class, new DbtPipelineClassConverter()),
Map.entry(GCSConfig.class, new GCPConfigClassConverter()), Map.entry(GCSConfig.class, new GCPConfigClassConverter()),

View File

@ -0,0 +1,39 @@
/*
* Copyright 2021 Collate
* Licensed 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.openmetadata.service.secrets.converter;
import java.util.List;
import org.openmetadata.schema.services.connections.database.MysqlConnection;
import org.openmetadata.schema.services.connections.database.common.IamAuthConfig;
import org.openmetadata.schema.services.connections.database.common.basicAuth;
import org.openmetadata.service.util.JsonUtils;
/** Converter class to get an `DatalakeConnection` object. */
public class MysqlConnectionClassConverter extends ClassConverter {
private static final List<Class<?>> CONFIG_SOURCE_CLASSES = List.of(basicAuth.class, IamAuthConfig.class);
public MysqlConnectionClassConverter() {
super(MysqlConnection.class);
}
@Override
public Object convert(Object object) {
MysqlConnection mysqlConnection = (MysqlConnection) JsonUtils.convertValue(object, this.clazz);
tryToConvert(mysqlConnection.getAuthType(), CONFIG_SOURCE_CLASSES).ifPresent(mysqlConnection::setAuthType);
return mysqlConnection;
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 2021 Collate
* Licensed 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.openmetadata.service.secrets.converter;
import java.util.List;
import org.openmetadata.schema.services.connections.database.PostgresConnection;
import org.openmetadata.schema.services.connections.database.common.IamAuthConfig;
import org.openmetadata.schema.services.connections.database.common.basicAuth;
import org.openmetadata.service.util.JsonUtils;
/** Converter class to get an `DatalakeConnection` object. */
public class PostgresConnectionClassConverter extends ClassConverter {
private static final List<Class<?>> CONFIG_SOURCE_CLASSES = List.of(basicAuth.class, IamAuthConfig.class);
public PostgresConnectionClassConverter() {
super(PostgresConnection.class);
}
@Override
public Object convert(Object object) {
PostgresConnection postgresConnection = (PostgresConnection) JsonUtils.convertValue(object, this.clazz);
tryToConvert(postgresConnection.getAuthType(), CONFIG_SOURCE_CLASSES).ifPresent(postgresConnection::setAuthType);
return postgresConnection;
}
}

View File

@ -16,6 +16,7 @@ import org.openmetadata.schema.entity.automations.Workflow;
import org.openmetadata.schema.entity.automations.WorkflowType; import org.openmetadata.schema.entity.automations.WorkflowType;
import org.openmetadata.schema.entity.services.ServiceType; import org.openmetadata.schema.entity.services.ServiceType;
import org.openmetadata.schema.services.connections.database.MysqlConnection; import org.openmetadata.schema.services.connections.database.MysqlConnection;
import org.openmetadata.schema.services.connections.database.common.basicAuth;
import org.openmetadata.service.Entity; import org.openmetadata.service.Entity;
import org.openmetadata.service.resources.EntityResourceTest; import org.openmetadata.service.resources.EntityResourceTest;
import org.openmetadata.service.resources.automations.WorkflowResource.WorkflowList; import org.openmetadata.service.resources.automations.WorkflowResource.WorkflowList;
@ -43,7 +44,7 @@ public class WorkflowResourceTest extends EntityResourceTest<Workflow, CreateWor
new MysqlConnection() new MysqlConnection()
.withHostPort("mysql:3306") .withHostPort("mysql:3306")
.withUsername("openmetadata_user") .withUsername("openmetadata_user")
.withPassword("openmetadata_password")))); .withAuthType(new basicAuth().withPassword("openmetadata_password")))));
} }
@Override @Override

View File

@ -52,6 +52,7 @@ import org.openmetadata.schema.services.connections.database.ConnectionOptions;
import org.openmetadata.schema.services.connections.database.MysqlConnection; import org.openmetadata.schema.services.connections.database.MysqlConnection;
import org.openmetadata.schema.services.connections.database.RedshiftConnection; import org.openmetadata.schema.services.connections.database.RedshiftConnection;
import org.openmetadata.schema.services.connections.database.SnowflakeConnection; import org.openmetadata.schema.services.connections.database.SnowflakeConnection;
import org.openmetadata.schema.services.connections.database.common.basicAuth;
import org.openmetadata.schema.type.ChangeDescription; import org.openmetadata.schema.type.ChangeDescription;
import org.openmetadata.schema.type.Schedule; import org.openmetadata.schema.type.Schedule;
import org.openmetadata.service.Entity; import org.openmetadata.service.Entity;
@ -387,9 +388,13 @@ public class DatabaseServiceResourceTest extends EntityResourceTest<DatabaseServ
assertEquals(expectedMysqlConnection.getConnectionOptions(), actualMysqlConnection.getConnectionOptions()); assertEquals(expectedMysqlConnection.getConnectionOptions(), actualMysqlConnection.getConnectionOptions());
assertEquals(expectedMysqlConnection.getConnectionArguments(), actualMysqlConnection.getConnectionArguments()); assertEquals(expectedMysqlConnection.getConnectionArguments(), actualMysqlConnection.getConnectionArguments());
if (maskedPasswords) { if (maskedPasswords) {
assertEquals(actualMysqlConnection.getPassword(), PasswordEntityMasker.PASSWORD_MASK); assertEquals(
JsonUtils.convertValue(actualMysqlConnection.getAuthType(), basicAuth.class).getPassword(),
PasswordEntityMasker.PASSWORD_MASK);
} else { } else {
assertEquals(expectedMysqlConnection.getPassword(), actualMysqlConnection.getPassword()); assertEquals(
JsonUtils.convertValue(expectedMysqlConnection.getAuthType(), basicAuth.class).getPassword(),
JsonUtils.convertValue(actualMysqlConnection.getAuthType(), basicAuth.class).getPassword());
} }
} }

View File

@ -41,6 +41,7 @@ import org.openmetadata.schema.security.secrets.Parameters;
import org.openmetadata.schema.security.secrets.SecretsManagerConfiguration; import org.openmetadata.schema.security.secrets.SecretsManagerConfiguration;
import org.openmetadata.schema.security.secrets.SecretsManagerProvider; import org.openmetadata.schema.security.secrets.SecretsManagerProvider;
import org.openmetadata.schema.services.connections.database.MysqlConnection; import org.openmetadata.schema.services.connections.database.MysqlConnection;
import org.openmetadata.schema.services.connections.database.common.basicAuth;
import org.openmetadata.schema.services.connections.metadata.OpenMetadataConnection; import org.openmetadata.schema.services.connections.metadata.OpenMetadataConnection;
import org.openmetadata.service.Entity; import org.openmetadata.service.Entity;
import org.openmetadata.service.exception.InvalidServiceConnectionException; import org.openmetadata.service.exception.InvalidServiceConnectionException;
@ -67,20 +68,20 @@ public abstract class ExternalSecretsManagerTest {
@Test @Test
void testEncryptDecryptDatabaseServiceConnectionConfig() { void testEncryptDecryptDatabaseServiceConnectionConfig() {
String password = "openmetadata-test"; String password = "openmetadata-test";
MysqlConnection expectedConnection = new MysqlConnection().withPassword(password); MysqlConnection expectedConnection = new MysqlConnection().withAuthType(new basicAuth().withPassword(password));
Map<String, String> mysqlConnection = Map.of("password", password); Map<String, Map<String, String>> mysqlConnection = Map.of("authType", Map.of("password", password));
// Ensure encrypted service connection config encrypts the password // Ensure encrypted service connection config encrypts the password
MysqlConnection actualConnection = MysqlConnection actualConnection =
(MysqlConnection) (MysqlConnection)
secretsManager.encryptServiceConnectionConfig(mysqlConnection, Mysql.value(), "test", ServiceType.DATABASE); secretsManager.encryptServiceConnectionConfig(mysqlConnection, Mysql.value(), "test", ServiceType.DATABASE);
assertNotEquals(password, actualConnection.getPassword()); assertNotEquals(password, JsonUtils.convertValue(actualConnection.getAuthType(), basicAuth.class).getPassword());
// Decrypt the encrypted password and validate // Decrypt the encrypted password and validate
actualConnection = actualConnection =
(MysqlConnection) (MysqlConnection)
secretsManager.decryptServiceConnectionConfig(mysqlConnection, Mysql.value(), ServiceType.DATABASE); secretsManager.decryptServiceConnectionConfig(mysqlConnection, Mysql.value(), ServiceType.DATABASE);
assertEquals(password, actualConnection.getPassword()); assertEquals(password, JsonUtils.convertValue(actualConnection.getAuthType(), basicAuth.class).getPassword());
assertEquals(expectedConnection, actualConnection); assertEquals(expectedConnection, actualConnection);
} }
@ -145,7 +146,8 @@ public abstract class ExternalSecretsManagerTest {
String secretKey = "secret:/openmetadata/serverconnection/securityconfig/secretkey"; String secretKey = "secret:/openmetadata/serverconnection/securityconfig/secretkey";
OpenMetadataConnection connection = OpenMetadataConnection connection =
new OpenMetadataConnection().withSecurityConfig(new GoogleSSOClientConfig().withSecretKey(secretKey)); new OpenMetadataConnection().withSecurityConfig(new GoogleSSOClientConfig().withSecretKey(secretKey));
DatabaseConnection dbConnection = new DatabaseConnection().withConfig(new MysqlConnection().withPassword(password)); DatabaseConnection dbConnection =
new DatabaseConnection().withConfig(new MysqlConnection().withAuthType(new basicAuth().withPassword(password)));
TestServiceConnectionRequest testRequest = TestServiceConnectionRequest testRequest =
new TestServiceConnectionRequest() new TestServiceConnectionRequest()
.withConnection(dbConnection) .withConnection(dbConnection)
@ -169,7 +171,8 @@ public abstract class ExternalSecretsManagerTest {
@Test @Test
void testExceptionConnection() { void testExceptionConnection() {
Map<String, String> mysqlConnection = Map.of("password", "openmetadata-test", "username1", "openmetadata-test"); Map<String, Object> mysqlConnection =
Map.of("username1", "openmetadata-test", "authType", Map.of("password", "openmetadata-test"));
InvalidServiceConnectionException thrown = InvalidServiceConnectionException thrown =
Assertions.assertThrows( Assertions.assertThrows(
InvalidServiceConnectionException.class, InvalidServiceConnectionException.class,
@ -209,8 +212,12 @@ public abstract class ExternalSecretsManagerTest {
} }
private String getPassword(Workflow workflow) { private String getPassword(Workflow workflow) {
return ((MysqlConnection) return JsonUtils.convertValue(
((DatabaseConnection) ((TestServiceConnectionRequest) workflow.getRequest()).getConnection()).getConfig()) ((MysqlConnection)
((DatabaseConnection) ((TestServiceConnectionRequest) workflow.getRequest()).getConnection())
.getConfig())
.getAuthType(),
basicAuth.class)
.getPassword(); .getPassword();
} }

View File

@ -29,8 +29,10 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.openmetadata.schema.entity.services.ServiceType; import org.openmetadata.schema.entity.services.ServiceType;
import org.openmetadata.schema.security.secrets.SecretsManagerProvider; import org.openmetadata.schema.security.secrets.SecretsManagerProvider;
import org.openmetadata.schema.services.connections.database.MysqlConnection; import org.openmetadata.schema.services.connections.database.MysqlConnection;
import org.openmetadata.schema.services.connections.database.common.basicAuth;
import org.openmetadata.schema.services.connections.mlmodel.SklearnConnection; import org.openmetadata.schema.services.connections.mlmodel.SklearnConnection;
import org.openmetadata.service.fernet.Fernet; import org.openmetadata.service.fernet.Fernet;
import org.openmetadata.service.util.JsonUtils;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
public class NoopSecretsManagerTest { public class NoopSecretsManagerTest {
@ -85,18 +87,22 @@ public class NoopSecretsManagerTest {
} }
private void testEncryptServiceConnection() { private void testEncryptServiceConnection() {
MysqlConnection connection = new MysqlConnection().withPassword(ENCRYPTED_VALUE); MysqlConnection connection = new MysqlConnection().withAuthType(new basicAuth().withPassword(ENCRYPTED_VALUE));
Object actualConfig = Object actualConfig =
secretsManager.encryptServiceConnectionConfig(connection, Mysql.value(), "test", ServiceType.DATABASE); secretsManager.encryptServiceConnectionConfig(connection, Mysql.value(), "test", ServiceType.DATABASE);
assertEquals(ENCRYPTED_VALUE, ((MysqlConnection) actualConfig).getPassword()); assertEquals(
ENCRYPTED_VALUE,
JsonUtils.convertValue(((MysqlConnection) actualConfig).getAuthType(), basicAuth.class).getPassword());
assertNotSame(connection, actualConfig); assertNotSame(connection, actualConfig);
} }
private void testDecryptServiceConnection() { private void testDecryptServiceConnection() {
MysqlConnection mysqlConnection = new MysqlConnection().withPassword(DECRYPTED_VALUE); MysqlConnection mysqlConnection = new MysqlConnection().withAuthType(new basicAuth().withPassword(DECRYPTED_VALUE));
Object actualConfig = Object actualConfig =
secretsManager.decryptServiceConnectionConfig(mysqlConnection, Mysql.value(), ServiceType.DATABASE); secretsManager.decryptServiceConnectionConfig(mysqlConnection, Mysql.value(), ServiceType.DATABASE);
assertEquals(DECRYPTED_VALUE, ((MysqlConnection) actualConfig).getPassword()); assertEquals(
DECRYPTED_VALUE,
JsonUtils.convertValue(((MysqlConnection) actualConfig).getAuthType(), basicAuth.class).getPassword());
assertNotSame(mysqlConnection, actualConfig); assertNotSame(mysqlConnection, actualConfig);
} }
} }

View File

@ -17,6 +17,8 @@ import org.openmetadata.schema.services.connections.dashboard.SupersetConnection
import org.openmetadata.schema.services.connections.dashboard.TableauConnection; import org.openmetadata.schema.services.connections.dashboard.TableauConnection;
import org.openmetadata.schema.services.connections.database.BigQueryConnection; import org.openmetadata.schema.services.connections.database.BigQueryConnection;
import org.openmetadata.schema.services.connections.database.DatalakeConnection; import org.openmetadata.schema.services.connections.database.DatalakeConnection;
import org.openmetadata.schema.services.connections.database.MysqlConnection;
import org.openmetadata.schema.services.connections.database.PostgresConnection;
import org.openmetadata.schema.services.connections.database.datalake.GCSConfig; import org.openmetadata.schema.services.connections.database.datalake.GCSConfig;
import org.openmetadata.schema.services.connections.metadata.OpenMetadataConnection; import org.openmetadata.schema.services.connections.metadata.OpenMetadataConnection;
import org.openmetadata.schema.services.connections.pipeline.AirflowConnection; import org.openmetadata.schema.services.connections.pipeline.AirflowConnection;
@ -30,6 +32,8 @@ public class ClassConverterFactoryTest {
AirflowConnection.class, AirflowConnection.class,
BigQueryConnection.class, BigQueryConnection.class,
DatalakeConnection.class, DatalakeConnection.class,
MysqlConnection.class,
PostgresConnection.class,
DbtGCSConfig.class, DbtGCSConfig.class,
DbtPipeline.class, DbtPipeline.class,
GCSConfig.class, GCSConfig.class,
@ -49,6 +53,6 @@ public class ClassConverterFactoryTest {
@Test @Test
void testClassConvertedMapIsNotModified() { void testClassConvertedMapIsNotModified() {
assertEquals(ClassConverterFactory.getConverterMap().size(), 15); assertEquals(ClassConverterFactory.getConverterMap().size(), 17);
} }
} }

View File

@ -19,8 +19,8 @@ public class PasswordEntityMaskerTest extends TestEntityMasker {
@Test @Test
void testExceptionConnection() { void testExceptionConnection() {
Map<String, String> mysqlConnectionObject = Map<String, Object> mysqlConnectionObject =
Map.of("password", "openmetadata-test", "username1", "openmetadata-test"); Map.of("authType", Map.of("password", "openmetadata-test"), "username1", "openmetadata-test");
EntityMaskException thrown = EntityMaskException thrown =
Assertions.assertThrows( Assertions.assertThrows(

View File

@ -26,9 +26,11 @@ import org.openmetadata.schema.services.connections.dashboard.SupersetConnection
import org.openmetadata.schema.services.connections.database.BigQueryConnection; import org.openmetadata.schema.services.connections.database.BigQueryConnection;
import org.openmetadata.schema.services.connections.database.DatalakeConnection; import org.openmetadata.schema.services.connections.database.DatalakeConnection;
import org.openmetadata.schema.services.connections.database.MysqlConnection; import org.openmetadata.schema.services.connections.database.MysqlConnection;
import org.openmetadata.schema.services.connections.database.common.basicAuth;
import org.openmetadata.schema.services.connections.database.datalake.GCSConfig; import org.openmetadata.schema.services.connections.database.datalake.GCSConfig;
import org.openmetadata.schema.services.connections.metadata.OpenMetadataConnection; import org.openmetadata.schema.services.connections.metadata.OpenMetadataConnection;
import org.openmetadata.schema.services.connections.pipeline.AirflowConnection; import org.openmetadata.schema.services.connections.pipeline.AirflowConnection;
import org.openmetadata.service.util.JsonUtils;
abstract class TestEntityMasker { abstract class TestEntityMasker {
@ -51,12 +53,18 @@ abstract class TestEntityMasker {
EntityMaskerFactory.createEntityMasker() EntityMaskerFactory.createEntityMasker()
.maskServiceConnectionConfig(airflowConnection, "Airflow", ServiceType.PIPELINE); .maskServiceConnectionConfig(airflowConnection, "Airflow", ServiceType.PIPELINE);
assertNotNull(masked); assertNotNull(masked);
assertEquals(((MysqlConnection) masked.getConnection()).getPassword(), getMaskedPassword()); assertEquals(
(JsonUtils.convertValue(((MysqlConnection) masked.getConnection()).getAuthType(), basicAuth.class)
.getPassword()),
getMaskedPassword());
AirflowConnection unmasked = AirflowConnection unmasked =
(AirflowConnection) (AirflowConnection)
EntityMaskerFactory.createEntityMasker() EntityMaskerFactory.createEntityMasker()
.unmaskServiceConnectionConfig(masked, airflowConnection, "Airflow", ServiceType.PIPELINE); .unmaskServiceConnectionConfig(masked, airflowConnection, "Airflow", ServiceType.PIPELINE);
assertEquals(((MysqlConnection) unmasked.getConnection()).getPassword(), PASSWORD); assertEquals(
JsonUtils.convertValue(((MysqlConnection) unmasked.getConnection()).getAuthType(), basicAuth.class)
.getPassword(),
PASSWORD);
} }
@Test @Test
@ -158,12 +166,17 @@ abstract class TestEntityMasker {
EntityMaskerFactory.createEntityMasker() EntityMaskerFactory.createEntityMasker()
.maskServiceConnectionConfig(supersetConnection, "Superset", ServiceType.DASHBOARD); .maskServiceConnectionConfig(supersetConnection, "Superset", ServiceType.DASHBOARD);
assertNotNull(masked); assertNotNull(masked);
assertEquals(((MysqlConnection) masked.getConnection()).getPassword(), getMaskedPassword()); assertEquals(
JsonUtils.convertValue(((MysqlConnection) masked.getConnection()).getAuthType(), basicAuth.class).getPassword(),
getMaskedPassword());
SupersetConnection unmasked = SupersetConnection unmasked =
(SupersetConnection) (SupersetConnection)
EntityMaskerFactory.createEntityMasker() EntityMaskerFactory.createEntityMasker()
.unmaskServiceConnectionConfig(masked, supersetConnection, "Superset", ServiceType.DASHBOARD); .unmaskServiceConnectionConfig(masked, supersetConnection, "Superset", ServiceType.DASHBOARD);
assertEquals(((MysqlConnection) unmasked.getConnection()).getPassword(), PASSWORD); assertEquals(
JsonUtils.convertValue(((MysqlConnection) unmasked.getConnection()).getAuthType(), basicAuth.class)
.getPassword(),
PASSWORD);
} }
@Test @Test
@ -179,8 +192,12 @@ abstract class TestEntityMasker {
Workflow masked = EntityMaskerFactory.createEntityMasker().maskWorkflow(workflow); Workflow masked = EntityMaskerFactory.createEntityMasker().maskWorkflow(workflow);
assertNotNull(masked); assertNotNull(masked);
assertEquals( assertEquals(
((MysqlConnection) JsonUtils.convertValue(
((DatabaseConnection) ((TestServiceConnectionRequest) masked.getRequest()).getConnection()).getConfig()) ((MysqlConnection)
((DatabaseConnection) ((TestServiceConnectionRequest) masked.getRequest()).getConnection())
.getConfig())
.getAuthType(),
basicAuth.class)
.getPassword(), .getPassword(),
getMaskedPassword()); getMaskedPassword());
assertEquals( assertEquals(
@ -188,9 +205,12 @@ abstract class TestEntityMasker {
getMaskedPassword()); getMaskedPassword());
Workflow unmasked = EntityMaskerFactory.createEntityMasker().unmaskWorkflow(masked, workflow); Workflow unmasked = EntityMaskerFactory.createEntityMasker().unmaskWorkflow(masked, workflow);
assertEquals( assertEquals(
((MysqlConnection) JsonUtils.convertValue(
((DatabaseConnection) ((TestServiceConnectionRequest) unmasked.getRequest()).getConnection()) ((MysqlConnection)
.getConfig()) ((DatabaseConnection) ((TestServiceConnectionRequest) unmasked.getRequest()).getConnection())
.getConfig())
.getAuthType(),
basicAuth.class)
.getPassword(), .getPassword(),
PASSWORD); PASSWORD);
assertEquals( assertEquals(
@ -206,12 +226,12 @@ abstract class TestEntityMasker {
EntityMaskerFactory.createEntityMasker() EntityMaskerFactory.createEntityMasker()
.maskServiceConnectionConfig(mysqlConnection, "Mysql", ServiceType.DATABASE); .maskServiceConnectionConfig(mysqlConnection, "Mysql", ServiceType.DATABASE);
assertNotNull(masked); assertNotNull(masked);
assertEquals(masked.getPassword(), getMaskedPassword()); assertEquals(JsonUtils.convertValue(masked.getAuthType(), basicAuth.class).getPassword(), getMaskedPassword());
MysqlConnection unmasked = MysqlConnection unmasked =
(MysqlConnection) (MysqlConnection)
EntityMaskerFactory.createEntityMasker() EntityMaskerFactory.createEntityMasker()
.unmaskServiceConnectionConfig(masked, mysqlConnection, "Mysql", ServiceType.DATABASE); .unmaskServiceConnectionConfig(masked, mysqlConnection, "Mysql", ServiceType.DATABASE);
assertEquals(unmasked.getPassword(), PASSWORD); assertEquals(JsonUtils.convertValue(unmasked.getAuthType(), basicAuth.class).getPassword(), PASSWORD);
} }
protected String getMaskedPassword() { protected String getMaskedPassword() {
@ -223,7 +243,7 @@ abstract class TestEntityMasker {
} }
private MysqlConnection buildMysqlConnection() { private MysqlConnection buildMysqlConnection() {
return new MysqlConnection().withPassword(PASSWORD); return new MysqlConnection().withAuthType(new basicAuth().withPassword(PASSWORD));
} }
private GCSConfig buildGcsConfig() { private GCSConfig buildGcsConfig() {

View File

@ -37,6 +37,7 @@ import org.openmetadata.schema.entity.services.DatabaseService;
import org.openmetadata.schema.entity.teams.Team; import org.openmetadata.schema.entity.teams.Team;
import org.openmetadata.schema.services.connections.dashboard.TableauConnection; import org.openmetadata.schema.services.connections.dashboard.TableauConnection;
import org.openmetadata.schema.services.connections.database.MysqlConnection; import org.openmetadata.schema.services.connections.database.MysqlConnection;
import org.openmetadata.schema.services.connections.database.common.basicAuth;
/** This test provides examples of how to use applyPatch */ /** This test provides examples of how to use applyPatch */
@Slf4j @Slf4j
@ -133,7 +134,9 @@ class JsonUtilsTest {
DatabaseService databaseService = DatabaseService databaseService =
new DatabaseService() new DatabaseService()
.withName("test") .withName("test")
.withConnection(new DatabaseConnection().withConfig(new MysqlConnection().withPassword("password"))); .withConnection(
new DatabaseConnection()
.withConfig(new MysqlConnection().withAuthType(new basicAuth().withPassword("password"))));
String actualJson = JsonUtils.pojoToMaskedJson(databaseService); String actualJson = JsonUtils.pojoToMaskedJson(databaseService);
assertEquals(expectedJson, actualJson); assertEquals(expectedJson, actualJson);
} }

View File

@ -61,6 +61,7 @@ import org.openmetadata.schema.services.connections.database.BigQueryConnection;
import org.openmetadata.schema.services.connections.database.MysqlConnection; import org.openmetadata.schema.services.connections.database.MysqlConnection;
import org.openmetadata.schema.services.connections.database.RedshiftConnection; import org.openmetadata.schema.services.connections.database.RedshiftConnection;
import org.openmetadata.schema.services.connections.database.SnowflakeConnection; import org.openmetadata.schema.services.connections.database.SnowflakeConnection;
import org.openmetadata.schema.services.connections.database.common.basicAuth;
import org.openmetadata.schema.services.connections.messaging.KafkaConnection; import org.openmetadata.schema.services.connections.messaging.KafkaConnection;
import org.openmetadata.schema.services.connections.messaging.RedpandaConnection; import org.openmetadata.schema.services.connections.messaging.RedpandaConnection;
import org.openmetadata.schema.services.connections.metadata.AmundsenConnection; import org.openmetadata.schema.services.connections.metadata.AmundsenConnection;
@ -142,7 +143,11 @@ public final class TestUtils {
static { static {
MYSQL_DATABASE_CONNECTION = MYSQL_DATABASE_CONNECTION =
new DatabaseConnection() new DatabaseConnection()
.withConfig(new MysqlConnection().withHostPort("localhost:3306").withUsername("test").withPassword("test")); .withConfig(
new MysqlConnection()
.withHostPort("localhost:3306")
.withUsername("test")
.withAuthType(new basicAuth().withPassword("test")));
REDSHIFT_DATABASE_CONNECTION = REDSHIFT_DATABASE_CONNECTION =
new DatabaseConnection() new DatabaseConnection()
.withConfig( .withConfig(

View File

@ -0,0 +1,17 @@
{
"$id": "https://open-metadata.org/schema/entity/services/connections/database/common/basicAuth.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Basic Auth",
"description": "Common Database Connection Config",
"javaType": "org.openmetadata.schema.services.connections.database.common.basicAuth",
"type": "object",
"properties": {
"password": {
"title": "Password",
"description": "Password to connect to source.",
"type": "string",
"format": "password"
}
},
"additionalProperties": false
}

View File

@ -0,0 +1,15 @@
{
"$id": "https://open-metadata.org/schema/entity/services/connections/database/common/iamAuthConfig.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "IAM Auth Configuration Source",
"description": "IAM Auth Database Connection Config",
"type": "object",
"javaType": "org.openmetadata.schema.services.connections.database.common.IamAuthConfig",
"properties": {
"awsConfig": {
"title": "AWS Credentials Configuration",
"$ref": "../../../../../security/credentials/awsCredentials.json"
}
},
"additionalProperties": false
}

View File

@ -37,11 +37,17 @@
"description": "Username to connect to MySQL. This user should have privileges to read all the metadata in Mysql.", "description": "Username to connect to MySQL. This user should have privileges to read all the metadata in Mysql.",
"type": "string" "type": "string"
}, },
"password": { "authType": {
"title": "Password", "title": "Auth Configuration Type",
"description": "Password to connect to MySQL.", "description": "Choose Auth Config Type.",
"type": "string", "oneOf": [
"format": "password" {
"$ref": "./common/basicAuth.json"
},
{
"$ref": "./common/iamAuthConfig.json"
}
]
}, },
"hostPort": { "hostPort": {
"title": "Host and Port", "title": "Host and Port",

View File

@ -9,13 +9,17 @@
"postgresType": { "postgresType": {
"description": "Service type.", "description": "Service type.",
"type": "string", "type": "string",
"enum": ["Postgres"], "enum": [
"Postgres"
],
"default": "Postgres" "default": "Postgres"
}, },
"postgresScheme": { "postgresScheme": {
"description": "SQLAlchemy driver scheme options.", "description": "SQLAlchemy driver scheme options.",
"type": "string", "type": "string",
"enum": ["postgresql+psycopg2"], "enum": [
"postgresql+psycopg2"
],
"default": "postgresql+psycopg2" "default": "postgresql+psycopg2"
} }
}, },
@ -37,15 +41,21 @@
"description": "Username to connect to Postgres. This user should have privileges to read all the metadata in Postgres.", "description": "Username to connect to Postgres. This user should have privileges to read all the metadata in Postgres.",
"type": "string" "type": "string"
}, },
"password": { "authType": {
"title": "Password", "title": "Auth Configuration Type",
"description": "Password to connect to Postgres.", "description": "Choose Auth Config Type.",
"type": "string", "oneOf": [
"format": "password" {
"$ref": "./common/basicAuth.json"
},
{
"$ref": "./common/iamAuthConfig.json"
}
]
}, },
"hostPort": { "hostPort": {
"title": "Host and Port", "title": "Host and Port",
"description": "Host and port of the Postgres service.", "description": "Host and port of the source service.",
"type": "string" "type": "string"
}, },
"database": { "database": {
@ -56,7 +66,14 @@
"sslMode": { "sslMode": {
"title": "SSL Mode", "title": "SSL Mode",
"description": "SSL Mode to connect to postgres database.", "description": "SSL Mode to connect to postgres database.",
"enum": ["disable", "allow", "prefer", "require", "verify-ca", "verify-full"], "enum": [
"disable",
"allow",
"prefer",
"require",
"verify-ca",
"verify-full"
],
"default": "disable" "default": "disable"
}, },
"sslConfig": { "sslConfig": {
@ -109,5 +126,9 @@
} }
}, },
"additionalProperties": false, "additionalProperties": false,
"required": ["hostPort", "username", "database"] "required": [
} "hostPort",
"username",
"database"
]
}

View File

@ -1045,7 +1045,7 @@ export const updateOwner = () => {
export const mySqlConnectionInput = () => { export const mySqlConnectionInput = () => {
cy.get('#root\\/username').type(Cypress.env('mysqlUsername')); cy.get('#root\\/username').type(Cypress.env('mysqlUsername'));
checkServiceFieldSectionHighlighting('username'); checkServiceFieldSectionHighlighting('username');
cy.get('#root\\/password').type(Cypress.env('mysqlPassword')); cy.get('#root\\/authType\\/password').type(Cypress.env('mysqlPassword'));
checkServiceFieldSectionHighlighting('password'); checkServiceFieldSectionHighlighting('password');
cy.get('#root\\/hostPort').type(Cypress.env('mysqlHostPort')); cy.get('#root\\/hostPort').type(Cypress.env('mysqlHostPort'));
checkServiceFieldSectionHighlighting('hostPort'); checkServiceFieldSectionHighlighting('hostPort');

View File

@ -53,7 +53,7 @@ describe('Postgres Ingestion', () => {
.scrollIntoView() .scrollIntoView()
.type(Cypress.env('postgresUsername')); .type(Cypress.env('postgresUsername'));
checkServiceFieldSectionHighlighting('username'); checkServiceFieldSectionHighlighting('username');
cy.get('#root\\/password') cy.get('#root\\/authType\\/password')
.scrollIntoView() .scrollIntoView()
.type(Cypress.env('postgresPassword')); .type(Cypress.env('postgresPassword'));
checkServiceFieldSectionHighlighting('password'); checkServiceFieldSectionHighlighting('password');

View File

@ -41,11 +41,103 @@ $$section
Username to connect to MySQL. This user should have access to the `INFORMATION_SCHEMA` to extract metadata. Other workflows may require different permissions -- refer to the section above for more information. Username to connect to MySQL. This user should have access to the `INFORMATION_SCHEMA` to extract metadata. Other workflows may require different permissions -- refer to the section above for more information.
$$ $$
## Basic Auth
$$section $$section
### Password $(id="password") ### Password $(id="password")
Password to connect to MySQL. Password to connect to MySQL.
$$ $$
## IAM Auth Config
### Note: If you are using IAM auth, add `"ssl": {"ssl-mode": "allow"} under Connection Arguments`
$$section
### AWS Access Key ID $(id="awsAccessKeyId")
When you interact with AWS, you specify your AWS security credentials to verify who you are and whether you have permission to access the resources that you are requesting. AWS uses the security credentials to authenticate and authorize your requests ([docs](https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html)).
Access keys consist of two parts:
1. An access key ID (for example, `AKIAIOSFODNN7EXAMPLE`),
2. And a secret access key (for example, `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`).
You must use both the access key ID and secret access key together to authenticate your requests.
You can find further information on how to manage your access keys [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html)
$$
$$section
### AWS Secret Access Key $(id="awsSecretAccessKey")
Secret access key (for example, `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`).
$$
$$section
### AWS Region $(id="awsRegion")
Each AWS Region is a separate geographic area in which AWS clusters data centers ([docs](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html)).
As AWS can have instances in multiple regions, we need to know the region the service you want reach belongs to.
Note that the AWS Region is the only required parameter when configuring a connection. When connecting to the services programmatically, there are different ways in which we can extract and use the rest of AWS configurations. You can find further information about configuring your credentials [here](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#configuring-credentials).
$$
$$section
### AWS Session Token $(id="awsSessionToken")
If you are using temporary credentials to access your services, you will need to inform the AWS Access Key ID and AWS Secrets Access Key. Also, these will include an AWS Session Token.
You can find more information on [Using temporary credentials with AWS resources](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html).
$$
$$section
### Endpoint URL $(id="endPointURL")
To connect programmatically to an AWS service, you use an endpoint. An *endpoint* is the URL of the entry point for an AWS web service. The AWS SDKs and the AWS Command Line Interface (AWS CLI) automatically use the default endpoint for each service in an AWS Region. But you can specify an alternate endpoint for your API requests.
Find more information on [AWS service endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html).
$$
$$section
### Profile Name $(id="profileName")
A named profile is a collection of settings and credentials that you can apply to an AWS CLI command. When you specify a profile to run a command, the settings and credentials are used to run that command. Multiple named profiles can be stored in the config and credentials files.
You can inform this field if you'd like to use a profile other than `default`.
Find here more information about [Named profiles for the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html).
$$
$$section
### Assume Role ARN $(id="assumeRoleArn")
Typically, you use `AssumeRole` within your account or for cross-account access. In this field you'll set the `ARN` (Amazon Resource Name) of the policy of the other account.
A user who wants to access a role in a different account must also have permissions that are delegated from the account administrator. The administrator must attach a policy that allows the user to call `AssumeRole` for the `ARN` of the role in the other account.
This is a required field if you'd like to `AssumeRole`.
Find more information on [AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html).
$$
$$section
### Assume Role Session Name $(id="assumeRoleSessionName")
An identifier for the assumed role session. Use the role session name to uniquely identify a session when the same role is assumed by different principals or for different reasons.
By default, we'll use the name `OpenMetadataSession`.
Find more information about the [Role Session Name](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html#:~:text=An%20identifier%20for%20the%20assumed%20role%20session.).
$$
$$section
### Assume Role Source Identity $(id="assumeRoleSourceIdentity")
The source identity specified by the principal that is calling the `AssumeRole` operation. You can use source identity information in AWS CloudTrail logs to determine who took actions with a role.
Find more information about [Source Identity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html#:~:text=Required%3A%20No-,SourceIdentity,-The%20source%20identity).
$$
$$section $$section
### Host Port $(id="hostPort") ### Host Port $(id="hostPort")
Host and port of the MySQL service. This should be specified as a string in the format `hostname:port`. E.g., `localhost:3306`, `host.docker.internal:3306`. Host and port of the MySQL service. This should be specified as a string in the format `hostname:port`. E.g., `localhost:3306`, `host.docker.internal:3306`.
@ -88,4 +180,5 @@ $$
$$section $$section
### Connection Arguments $(id="connectionArguments") ### Connection Arguments $(id="connectionArguments")
Additional connection arguments such as security or protocol configs that can be sent to the service during connection. Additional connection arguments such as security or protocol configs that can be sent to the service during connection.
#### Note: If you are using IAM auth, add `"ssl": {"ssl-mode": "allow"} under Connection Arguments`
$$ $$

View File

@ -45,13 +45,101 @@ $$section
Username to connect to Postgres. This user should have privileges to read all the metadata in Postgres. Username to connect to Postgres. This user should have privileges to read all the metadata in Postgres.
$$ $$
## Basic Auth
$$section $$section
### Password $(id="password") ### Password $(id="password")
Password to connect to Postgres. Password to connect to Postgres.
$$ $$
## IAM Auth Config
$$section
### AWS Access Key ID $(id="awsAccessKeyId")
When you interact with AWS, you specify your AWS security credentials to verify who you are and whether you have permission to access the resources that you are requesting. AWS uses the security credentials to authenticate and authorize your requests ([docs](https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html)).
Access keys consist of two parts:
1. An access key ID (for example, `AKIAIOSFODNN7EXAMPLE`),
2. And a secret access key (for example, `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`).
You must use both the access key ID and secret access key together to authenticate your requests.
You can find further information on how to manage your access keys [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html)
$$
$$section
### AWS Secret Access Key $(id="awsSecretAccessKey")
Secret access key (for example, `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`).
$$
$$section
### AWS Region $(id="awsRegion")
Each AWS Region is a separate geographic area in which AWS clusters data centers ([docs](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html)).
As AWS can have instances in multiple regions, we need to know the region the service you want reach belongs to.
Note that the AWS Region is the only required parameter when configuring a connection. When connecting to the services programmatically, there are different ways in which we can extract and use the rest of AWS configurations. You can find further information about configuring your credentials [here](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#configuring-credentials).
$$
$$section
### AWS Session Token $(id="awsSessionToken")
If you are using temporary credentials to access your services, you will need to inform the AWS Access Key ID and AWS Secrets Access Key. Also, these will include an AWS Session Token.
You can find more information on [Using temporary credentials with AWS resources](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html).
$$
$$section
### Endpoint URL $(id="endPointURL")
To connect programmatically to an AWS service, you use an endpoint. An *endpoint* is the URL of the entry point for an AWS web service. The AWS SDKs and the AWS Command Line Interface (AWS CLI) automatically use the default endpoint for each service in an AWS Region. But you can specify an alternate endpoint for your API requests.
Find more information on [AWS service endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html).
$$
$$section
### Profile Name $(id="profileName")
A named profile is a collection of settings and credentials that you can apply to an AWS CLI command. When you specify a profile to run a command, the settings and credentials are used to run that command. Multiple named profiles can be stored in the config and credentials files.
You can inform this field if you'd like to use a profile other than `default`.
Find here more information about [Named profiles for the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html).
$$
$$section
### Assume Role ARN $(id="assumeRoleArn")
Typically, you use `AssumeRole` within your account or for cross-account access. In this field you'll set the `ARN` (Amazon Resource Name) of the policy of the other account.
A user who wants to access a role in a different account must also have permissions that are delegated from the account administrator. The administrator must attach a policy that allows the user to call `AssumeRole` for the `ARN` of the role in the other account.
This is a required field if you'd like to `AssumeRole`.
Find more information on [AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html).
$$
$$section
### Assume Role Session Name $(id="assumeRoleSessionName")
An identifier for the assumed role session. Use the role session name to uniquely identify a session when the same role is assumed by different principals or for different reasons.
By default, we'll use the name `OpenMetadataSession`.
Find more information about the [Role Session Name](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html#:~:text=An%20identifier%20for%20the%20assumed%20role%20session.).
$$
$$section
### Assume Role Source Identity $(id="assumeRoleSourceIdentity")
The source identity specified by the principal that is calling the `AssumeRole` operation. You can use source identity information in AWS CloudTrail logs to determine who took actions with a role.
Find more information about [Source Identity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html#:~:text=Required%3A%20No-,SourceIdentity,-The%20source%20identity).
$$
$$section $$section
### Host and Port $(id="hostPort") ### Host and Port $(id="hostPort")
@ -68,6 +156,7 @@ $$section
### SSL Mode $(id="sslMode") ### SSL Mode $(id="sslMode")
SSL Mode to connect to postgres database. E.g, `prefer`, `verify-ca` etc. SSL Mode to connect to postgres database. E.g, `prefer`, `verify-ca` etc.
#### Note: if you are using `IAM auth`, select either `allow` (recommended) or other option based on your use case.
$$ $$
$$section $$section