| Server IP : 185.208.173.17 / Your IP : 87.236.161.98 Web Server : Microsoft-IIS/10.0 System : Windows NT SRV8576125506 10.0 build 26100 (Windows Server 2016) AMD64 User : IUSR ( 0) PHP Version : 7.4.13 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : C:/Program Files/MySQL/MySQL Workbench 8.0/swb/shell/lib/mysqlsh/plugins/mrs_plugin/ |
Upload File : |
# Copyright (c) 2021, 2025, Oracle and/or its affiliates.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2.0,
# as published by the Free Software Foundation.
#
# This program is designed to work with certain software (including
# but not limited to OpenSSL) that is licensed under separate terms, as
# designated in a particular file or component or in included license
# documentation. The authors of MySQL hereby grant you an additional
# permission to link the program and your derivative works with the
# separately licensed software that they have either included with
# the program or referenced in the documentation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
# the GNU General Public License, version 2.0, for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""Sub-Module for managing MRS auth_apps"""
# cSpell:ignore mysqlsh, mrs
from mysqlsh.plugin_manager import plugin_function
import mrs_plugin.lib as lib
from .interactive import resolve_service, resolve_auth_app, resolve_file_path, resolve_overwrite_file, auth_app_query_selection, service_query_selection
import sys
def generate_create_statement(**kwargs) -> str:
lib.core.convert_ids_to_binary(["service_id", "auth_app_id"], kwargs)
lib.core.try_convert_ids_to_binary(["service", "schema"], kwargs)
include_all_objects = kwargs.get("include_all_objects", False)
auth_app_query = auth_app_query_selection(**kwargs)
service_query = service_query_selection(**kwargs)
with lib.core.MrsDbSession(exception_handler=lib.core.print_exception, **kwargs) as session:
auth_app = resolve_auth_app(
session, auth_app_query=auth_app_query, service_query=service_query)
return lib.auth_apps.get_auth_app_create_statement(session, auth_app, include_all_objects)
@plugin_function('mrs.get.authenticationVendors', shell=True, cli=True, web=True)
def get_auth_vendors(**kwargs):
"""Adds an auth_app to the given MRS service
Args:
**kwargs: Additional options
Keyword Args:
enabled (bool): Whether to return just the enabled vendors (default) or all
session (object): The database session to use
Returns:
The list of vendor objects
"""
enabled = kwargs.get("enabled", True)
with lib.core.MrsDbSession(exception_handler=lib.core.print_exception, **kwargs) as session:
return lib.auth_apps.get_auth_vendors(session, enabled)
@plugin_function('mrs.add.authenticationApp', shell=True, cli=True, web=True)
def add_auth_app(app_name=None, service_id=None, **kwargs):
"""Adds an auth_app to the given MRS service
Args:
app_name (str): The app_name
service_id (str): The id of the service the schema should be added to
**kwargs: Additional options
Keyword Args:
auth_vendor_id (str): The auth_vendor_id
description (str): A description of the app
url (str): url of the app
url_direct_auth (str): url direct auth of the app
access_token (str): access_token of the app
app_id (str): app_id of the app
limit_to_registered_users (bool): Limit access to registered users
registered_users (list): List of registered users
default_role_id (str): The default role to be assigned to new users
enabled (int): Whether the Auth App is enabled
options (dict): Additional options
session (object): The database session to use
Returns:
A dict with content_set_id and number_of_files_uploaded
"""
if service_id:
service_id = lib.core.id_to_binary(service_id, "service_id")
lib.core.convert_ids_to_binary(
["auth_vendor_id", "default_role_id"], kwargs)
auth_vendor_id = kwargs.get("auth_vendor_id")
default_role_id = kwargs.get("default_role_id")
description = kwargs.get("description")
url = kwargs.get("url")
url_direct_auth = kwargs.get("url_direct_auth")
access_token = kwargs.get("access_token")
app_id = kwargs.get("app_id")
limit_to_reg_users = kwargs.get("limit_to_registered_users")
registered_users = kwargs.get("registered_users")
enabled = kwargs.get("enabled", 1)
options = kwargs.get("options")
interactive = lib.core.get_interactive_default()
with lib.core.MrsDbSession(exception_handler=lib.core.print_exception, **kwargs) as session:
if service_id is not None:
service = resolve_service(session, service_id)
if service is not None:
service_id = service["id"]
# Get auth_vendor_id
if not auth_vendor_id and interactive:
app_vendors = lib.core.select(table="auth_vendor",
cols=["id", "name"],
where="enabled=1"
).exec(session).items
if len(app_vendors) == 0:
raise ValueError("No authentication vendors enabled.")
app_vendor = lib.core.prompt_for_list_item(
item_list=app_vendors, prompt_caption=(
"Please select an authentication vendor: "),
item_name_property="name",
print_list=True)
if not app_vendor:
raise ValueError("Operation cancelled.")
auth_vendor_id = app_vendor['id']
if not auth_vendor_id:
raise ValueError("No authentication vendor specified.")
# Get app_name
if not app_name and interactive:
if auth_vendor_id == lib.auth_apps.MYSQL_AUTHENTICATION:
app_name = lib.core.prompt(
"Please enter the name of the authentication app "
"[MySQL Account Access]: ",
{'defaultValue': 'MySQL Account Access'})
else:
app_name = lib.core.prompt(
"Please enter the name of the authentication app: ")
if not app_name:
raise ValueError("Operation cancelled.")
if not app_name:
raise ValueError("No app name specified.")
# Get description
if not description and interactive:
if auth_vendor_id == lib.auth_apps.MYSQL_AUTHENTICATION:
description = lib.core.prompt(
"Please enter a description for the authentication app "
"[Authentication via MySQL accounts]",
{'defaultValue':
'Authentication via MySQL accounts'})
else:
description = lib.core.prompt(
"Please enter a description for the authentication app: ")
# Get limit_to_registered_users
if not limit_to_reg_users and interactive:
limit_to_reg_users = lib.core.prompt(
"Limit authentication to registered users? [y/N]: ",
{'defaultValue': 'n'}).strip().lower() == 'y'
# Get registered_users, convert to list
if limit_to_reg_users and not registered_users and interactive:
registered_users = lib.core.prompt(
"Please enter a list of registered user names, separated "
"by comma (,): ")
registered_users = registered_users.split(',')
registered_users = [reg_user.strip()
for reg_user in registered_users]
default_role_id = default_role_id or lib.auth_apps.DEFAULT_ROLE_ID
with lib.core.MrsDbTransaction(session):
# Create the auth_app
auth_app_id = lib.auth_apps.add_auth_app(session, service_id, auth_vendor_id,
app_name, description, url, url_direct_auth, access_token, app_id,
limit_to_reg_users, default_role_id, enabled, options)
# Create the registered_users if specified
if registered_users and len(registered_users) > 0:
role_comments = "Default role." if default_role_id == lib.auth_apps.DEFAULT_ROLE_ID else ""
for reg_user in registered_users:
user_id = lib.users.add_user(session, auth_app_id, reg_user, None, None, None,
None, None, None)
if default_role_id:
lib.users.add_user_role(
session, user_id, default_role_id, role_comments)
if lib.core.get_interactive_result():
return f"\nAuthentication app with the id {auth_app_id} was added successfully."
else:
return {
"auth_app_id": auth_app_id
}
@plugin_function('mrs.get.authenticationApp', shell=True, cli=True, web=True)
def get_auth_app(app_id=None, session=None):
"""Returns the requested authentication app
Args:
app_id (str): The application id
session (object): The database session to use.
Returns:
Either a string listing the content sets when interactive is set or list
of dicts representing the authentication app
"""
if app_id is not None:
app_id = lib.core.id_to_binary(app_id, "app_id")
with lib.core.MrsDbSession(exception_handler=lib.core.print_exception, session=session) as session:
auth_app = resolve_auth_app(session, auth_app_query=app_id)
if lib.core.get_interactive_result():
return lib.auth_apps.format_auth_app_listing(
auth_apps=auth_app, print_header=True)
return auth_app
@plugin_function('mrs.list.authenticationApps', shell=True, cli=True, web=True)
def get_auth_apps(service_id=None, **kwargs):
"""Returns all authentication apps for the given MRS service
Args:
service_id (str): The id of the service to list the schemas from
**kwargs: Additional options
Keyword Args:
include_enable_state (bool): Only include items with the given
enabled state
session (object): The database session to use.
Returns:
Either a string listing the content sets when interactive is set or list
of dicts representing the authentication apps
"""
if service_id is not None:
service_id = lib.core.id_to_binary(service_id, "service_id")
include_enable_state = kwargs.get("include_enable_state")
with lib.core.MrsDbSession(exception_handler=lib.core.print_exception, **kwargs) as session:
auth_apps = lib.auth_apps.get_auth_apps(
session, service_id, include_enable_state)
if lib.core.get_interactive_result():
return lib.auth_apps.format_auth_app_listing(
auth_apps=auth_apps, print_header=True)
else:
return auth_apps
@plugin_function('mrs.delete.authenticationApp', shell=True, cli=True, web=True)
def delete_auth_app(**kwargs):
"""Deletes an existing auth_app
Args:
**kwargs: Additional options
Keyword Args:
app_id (str): The application id
session (object): The database session to use
Returns:
None
"""
lib.core.convert_ids_to_binary(["app_id"], kwargs)
app_id = kwargs.get("app_id")
with lib.core.MrsDbSession(exception_handler=lib.core.print_exception, **kwargs) as session:
with lib.core.MrsDbTransaction(session):
lib.auth_apps.delete_auth_app(
session, app_id=app_id)
@plugin_function('mrs.update.authenticationApp', shell=True, cli=True, web=True)
def update_auth_app(**kwargs):
"""Updates an existing auth_app
Args:
**kwargs: Additional options
Keyword Args:
app_id (str): The application id
value (dict): The values as dict
service_id (str): The id of the service that this auth_app belongs to
auth_app_name (str): The name of the auth_app to update
session (object): The database session to use
Allowed options for value:
auth_vendor_id (str): The auth_vendor_id
name (str): The new name for the app
description (str): The new description
url (str): The new url for the app
url_direct_auth (str): The new url direct auth for the app
access_token (str): The new access token
app_id (str): The new application id
enabled (bool): Set if it's enabled or not
limit_to_registered_users (bool): Set if limited to registered users
default_role_id (str): The new default role id
options (dict): Additional options
Returns:
A dict with content_set_id and number_of_files_uploaded
"""
lib.core.convert_ids_to_binary(["app_id", "service_id"], kwargs)
lib.core.convert_ids_to_binary(
["default_role_id", "auth_vendor_id"], kwargs["value"])
app_id = kwargs.get("app_id")
with lib.core.MrsDbSession(exception_handler=lib.core.print_exception, **kwargs) as session:
value = kwargs.get("value")
lib.auth_apps.update_auth_app(session, app_id, value)
@plugin_function('mrs.get.authAppCreateStatement', shell=True, cli=True, web=True)
def get_auth_app_create_statement(**kwargs):
"""Returns the corresponding CREATE REST AUTH APP SQL statement of the given MRS service object.
When using the 'auth_app' parameter, you can choose either of these formats:
- '0x11EF8496143CFDEC969C7413EA499D96' - Hexadecimal string ID
- 'Ee+ElhQ8/eyWnHQT6kmdlg==' - Base64 string ID
- 'localhost/myService/authApp' - Human readable string ID
Args:
**kwargs: Options to determine what should be generated.
Keyword Args:
auth_app_id (str): The ID of the authentication app to generate.
service_id (str): The ID of the service where the authentication app belongs.
auth_app (str): The identifier of the authentication app.
include_all_objects (bool): Include all objects that belong to the authentication app.
session (object): The database session to use.
Returns:
The SQL that represents the create statement for the MRS schema
"""
return generate_create_statement(**kwargs)
@plugin_function('mrs.dump.authAppCreateStatement', shell=True, cli=True, web=True)
def store_auth_app_create_statement(**kwargs):
"""Stores the corresponding CREATE REST AUTH APP SQL statement of the given MRS schema
object into a file.
When using the 'auth_app' parameter, you can choose either of these formats:
- '0x11EF8496143CFDEC969C7413EA499D96' - Hexadecimal string ID
- 'Ee+ElhQ8/eyWnHQT6kmdlg==' - Base64 string ID
- 'localhost/myService/authApp/user' - Human readable string ID
Args:
**kwargs: Options to determine what should be generated.
Keyword Args:
auth_app_id (str): The ID of the authentication app to generate.
service_id (str): The ID of the service where the authentication app belongs.
auth_app (str): The identifier of the authentication app.
include_all_objects (bool): Include all objects that belong to the schema.
file_path (str): The path where to store the file.
overwrite (bool): Overwrite the file, if already exists.
session (object): The database session to use.
Returns:
True if the file was saved.
"""
file_path = kwargs.get("file_path")
overwrite = kwargs.get("overwrite")
file_path = resolve_file_path(file_path)
resolve_overwrite_file(file_path, overwrite)
sql = generate_create_statement(**kwargs)
with open(file_path, "w") as f:
f.write(sql)
if lib.core.get_interactive_result():
return f"File created in {file_path}."
return True
@plugin_function('mrs.get.ociDomainAppSecret', shell=True, cli=True, web=False)
def get_oci_domain_secret(domain_endpoint, app_name, **kwargs):
"""Prints the client secret for the given OCI domain app to stdout
Args:
domain_endpoint (str): The OCI domain HTTPS endpoint URL.
app_name (str): The OCI domain app name.
**kwargs: Additional options.
Keyword Args:
oci_profile (str): The name of the OCI profile to use. If omitted, the resource principal will be used.
Returns:
None
"""
import oci.auth.signers
import oci.config
import oci.identity_domains
oci_profile = kwargs.get("oci_profile", None)
try:
if oci_profile is None:
rps = oci.auth.signers.get_resource_principals_signer()
domainsClient = oci.identity_domains.IdentityDomainsClient(
config={}, service_endpoint=domain_endpoint, signer=rps)
else:
config = oci.config.from_file("~/.oci/config", oci_profile)
domainsClient = oci.identity_domains.IdentityDomainsClient(
config=config, service_endpoint=domain_endpoint)
# Lookup the app by name
response = domainsClient.list_apps(filter=f'name eq "{app_name}"')
# Check if the app was found
if not response.data or len(response.data.resources) < 1:
raise ValueError('The App could not be found.')
# Print the client_secret to stdout
print(response.data.resources[0].client_secret)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
@plugin_function('mrs.add.authenticationAppLink', shell=True, cli=True, web=True)
def link_auth_app(app_id, service_id, **kwargs):
"""Links a REST auth app to a REST service
Args:
app_id (str): The application id
service_id (str): The id of the service that this auth_app belongs to
**kwargs: Additional options
Keyword Args:
session (object): The database session to use
Returns:
None
"""
with lib.core.MrsDbSession(exception_handler=lib.core.print_exception, **kwargs) as session:
lib.auth_apps.link_auth_app(
session=session,
auth_app_id=lib.core.id_to_binary(app_id, "app_id"),
service_id=lib.core.id_to_binary(service_id, "service_id"))
@plugin_function('mrs.delete.authenticationAppLink', shell=True, cli=True, web=True)
def unlink_auth_app(app_id, service_id, **kwargs):
"""Unlinks a REST auth app to a REST service
Args:
app_id (str): The application id
service_id (str): The id of the service that this auth_app belongs to
**kwargs: Additional options
Keyword Args:
session (object): The database session to use
Returns:
None
"""
with lib.core.MrsDbSession(exception_handler=lib.core.print_exception, **kwargs) as session:
lib.auth_apps.unlink_auth_app(
session=session,
auth_app_id=lib.core.id_to_binary(app_id, "app_id"),
service_id=lib.core.id_to_binary(service_id, "service_id"))
@plugin_function('mrs.list.authenticationAppServices', shell=True, cli=True, web=True)
def get_auth_app_services(app_id=None, session=None):
"""Returns the list of REST services that a given authentication app is linked to
Args:
app_id (str): The application id
session (object): The database session to use.
Returns:
A list of dicts representing the services
"""
if app_id is not None:
app_id = lib.core.id_to_binary(app_id, "app_id")
with lib.core.MrsDbSession(exception_handler=lib.core.print_exception, session=session) as session:
services = lib.services.query_services(
session=session, auth_app_id=app_id)
if lib.core.get_interactive_result():
return lib.services.format_service_listing(services)
else:
return services