def sqlvm_add_to_group(client, cmd, sql_virtual_machine_name, resource_group_name, sql_virtual_machine_group_resource_id, sql_service_account_password=None, cluster_operator_account_password=None, cluster_bootstrap_account_password=None): ''' Adds a SQL virtual machine to a group. ''' sqlvm_object = client.get(resource_group_name, sql_virtual_machine_name) if not sql_service_account_password: sql_service_account_password = prompt_pass('SQL Service account password: '******'Cluster operator account password: '******'Password to authenticate with the domain controller.') sqlvm_object.sql_virtual_machine_group_resource_id = sql_virtual_machine_group_resource_id sqlvm_object.wsfc_domain_credentials = WsfcDomainCredentials(cluster_bootstrap_account_password=cluster_bootstrap_account_password, cluster_operator_account_password=cluster_operator_account_password, sql_service_account_password=sql_service_account_password) # Since it's a running operation, we will do the put and then the get to display the instance. LongRunningOperation(cmd.cli_ctx)(sdk_no_wait(False, client.create_or_update, resource_group_name, sql_virtual_machine_name, sqlvm_object)) return client.get(resource_group_name, sql_virtual_machine_name)
def update_adla_catalog_credential(client, account_name, database_name, credential_name, credential_user_name, uri, credential_user_password=None, new_credential_user_password=None): from azure.mgmt.datalake.analytics.catalog.models import DataLakeAnalyticsCatalogCredentialUpdateParameters if not credential_user_password: try: credential_user_password = prompt_pass('Current Password:'******'Please specify --user-name --password and --new-password in non-interactive mode.' ) if not new_credential_user_password: try: new_credential_user_password = prompt_pass('New Password:'******'Please specify --user-name --password and --new-password in non-interactive mode.' ) update_params = DataLakeAnalyticsCatalogCredentialUpdateParameters( credential_user_password, new_credential_user_password, uri, credential_user_name) client.update_credential(account_name, database_name, credential_name, update_params)
def _create_image_registry_credentials(registry_login_server, registry_username, registry_password, image): """Create image registry credentials. """ image_registry_credentials = None if registry_login_server: if not registry_username: raise CLIError('Please specify --registry-username in order to use custom image registry.') if not registry_password: try: registry_password = prompt_pass(msg='Image registry password: '******'Please specify --registry-password in order to use custom image registry.') image_registry_credentials = [ImageRegistryCredential(server=registry_login_server, username=registry_username, password=registry_password)] elif ACR_SERVER_SUFFIX in image: if not registry_password: try: registry_password = prompt_pass(msg='Image registry password: '******'Please specify --registry-password in order to use Azure Container Registry.') acr_server = image.split("/")[0] if image.split("/") else None acr_username = image.split(ACR_SERVER_SUFFIX)[0] if image.split(ACR_SERVER_SUFFIX) else None if acr_server and acr_username: image_registry_credentials = [ImageRegistryCredential(server=acr_server, username=acr_username, password=registry_password)] else: raise CLIError('Failed to parse ACR server or username from image name; please explicitly specify --registry-server and --registry-username.') return image_registry_credentials
def _get_credentials(cli_ctx, registry_name, resource_group_name, username, password, only_refresh_token, repository=None, permission='*'): """Try to get AAD authorization tokens or admin user credentials. :param str registry_name: The name of container registry :param str resource_group_name: The name of resource group :param str username: The username used to log into the container registry :param str password: The password used to log into the container registry :param bool only_refresh_token: Whether to ask for only refresh token, or for both refresh and access tokens :param str repository: Repository for which the access token is requested :param str permission: The requested permission on the repository, '*' or 'pull' """ registry, resource_group_name = get_registry_by_name(cli_ctx, registry_name, resource_group_name) login_server = registry.login_server # 1. if username was specified, verify that password was also specified if username: if not password: try: password = prompt_pass(msg='Password: '******'Please specify both username and password in non-interactive mode.') return login_server, username, password # 2. if we don't yet have credentials, attempt to get a refresh token if not password and registry.sku.name in MANAGED_REGISTRY_SKU: try: username = '******' if only_refresh_token else None password = _get_aad_token(cli_ctx, login_server, only_refresh_token, repository, permission) return login_server, username, password except CLIError as e: logger.warning("Unable to get AAD authorization tokens with message: %s", str(e)) # 3. if we still don't have credentials, attempt to get the admin credentials (if enabled) if not password and registry.admin_user_enabled: try: cred = cf_acr_registries(cli_ctx).list_credentials(resource_group_name, registry_name) username = cred.username password = cred.passwords[0].value return login_server, username, password except CLIError as e: logger.warning("Unable to get admin user credentials with message: %s", str(e)) # 4. if we still don't have credentials, prompt the user if not password: try: username = prompt('Username: '******'Password: '******'Unable to authenticate using AAD or admin login credentials. ' + 'Please specify both username and password in non-interactive mode.')
def test_prompt_pass_confirm_invalid(self, _): my_password1 = '7ndBkS3zKQazD5N3zzstubZq' my_password2 = 'LTQ9haNMCSGp8p2uQHw2K9xf' with mock.patch('logging.Logger.warning') as mock_log_warn: with self.assertRaises(StopIteration): with mock.patch('getpass.getpass', side_effect=[my_password1, my_password2]): prompt_pass(confirm=True) mock_log_warn.assert_called_once_with(_INVALID_PASSWORD_MSG)
def interactive_input(arg, hint): '''Get interactive inputs from users ''' value = None cmd_value = None if arg == 'secret_auth_info': name = prompt('User name of database (--secret name=): ') secret = prompt_pass('Password of database (--secret secret=): ') value = {'name': name, 'secret': secret, 'auth_type': 'secret'} cmd_value = 'name={} secret={}'.format(name, '*' * len(secret)) elif arg == 'service_principal_auth_info_secret': client_id = prompt( 'ServicePrincipal client-id (--service-principal client_id=): ') object_id = prompt( 'Enterprise Application object-id (--service-principal object-id=): ' ) secret = prompt_pass( 'ServicePrincipal secret (--service-principal secret=): ') value = { 'client_id': client_id, 'object-id': object_id, 'secret': secret, 'auth_type': 'servicePrincipalSecret' } cmd_value = 'client-id={} principal-id={} secret={}'.format( client_id, object_id, '*' * len(secret)) elif arg == 'user_identity_auth_info': client_id = prompt( 'UserAssignedIdentity client-id (--user-identity client_id=): ') subscription_id = prompt( 'UserAssignedIdentity subscription-id (--user-identity subs_id=): ' ) value = { 'client_id': client_id, 'subscription_id': subscription_id, 'auth_type': 'userAssignedIdentity' } cmd_value = 'client-id={} subscription-id={}'.format( client_id, subscription_id) else: value = prompt('{}: '.format(hint)) cmd_value = value # check blank value if isinstance(value, dict): for sub_val in value.values(): if not sub_val: raise RequiredArgumentMissingError( '{} should not be blank'.format(hint)) elif not value: raise RequiredArgumentMissingError( '{} should not be blank'.format(hint)) return value, cmd_value
def _create_image_registry_credentials(cmd, resource_group_name, registry_login_server, registry_username, registry_password, image, identity): from msrestazure.tools import is_valid_resource_id image_registry_credentials = None if registry_login_server: if not registry_username: raise RequiredArgumentMissingError('Please specify --registry-username in order to use custom image registry.') if not registry_password: try: registry_password = prompt_pass(msg='Image registry password: '******'Please specify --registry-password in order to use custom image registry.') image_registry_credentials = [ImageRegistryCredential(server=registry_login_server, username=registry_username, password=registry_password)] elif ACR_SERVER_DELIMITER in image.split("/")[0]: acr_server = image.split("/")[0] if image.split("/") else None if identity: if not is_valid_resource_id(identity): msi_client = cf_msi(cmd.cli_ctx) identity = msi_client.user_assigned_identities.get(resource_group_name=resource_group_name, resource_name=identity).id if acr_server: image_registry_credentials = [ImageRegistryCredential(server=acr_server, username=registry_username, password=registry_password, identity=identity)] else: if not registry_username: try: registry_username = prompt(msg='Image registry username: '******'Please specify --registry-username in order to use Azure Container Registry.') if not registry_password: try: registry_password = prompt_pass(msg='Image registry password: '******'Please specify --registry-password in order to use Azure Container Registry.') if acr_server: image_registry_credentials = [ImageRegistryCredential(server=acr_server, username=registry_username, password=registry_password)] elif registry_username and registry_password and SERVER_DELIMITER in image.split("/")[0]: login_server = image.split("/")[0] if image.split("/") else None if login_server: image_registry_credentials = [ImageRegistryCredential(server=login_server, username=registry_username, password=registry_password)] else: raise RequiredArgumentMissingError('Failed to parse login server from image name; please explicitly specify --registry-server.') return image_registry_credentials
def _create_token(self, note=None): logger.warning('We need to create a Personal Access Token to communicate with GitHub. ' 'A new PAT with scopes (admin:repo_hook, repo, user) will be created.') logger.warning('You can set the PAT in the environment variable (%s) to avoid getting prompted.', AZ_DEVOPS_GITHUB_PAT_ENVKEY) self.username = prompt(msg='Enter your GitHub username (leave blank for using already generated PAT): ') print('') if not self.username: while not self.token: self.token = prompt_pass(msg='Enter your GitHub PAT: ', help_string='Generate a Personal Access Token ' 'with approproate permissions from GitHub Developer settings and paste here.') print('') return self.password = prompt_pass(msg='Enter your GitHub password: '******'') if not note: note = "AzureDevopsCLIExtensionToken_" + datetime_now_as_string() encoded_pass = base64.b64encode(self.username.encode('utf-8') + b':' + self.password.encode('utf-8')) basic_auth = 'basic ' + encoded_pass.decode("utf-8") request_body = { 'scopes': [ 'admin:repo_hook', 'repo', 'user' ], 'note': note } headers = {'Content-Type': 'application/json' + '; charset=utf-8', 'Accept': 'application/json', 'Authorization': basic_auth} response = self.post_authorization_request(headers=headers, body=request_body) if (response.status_code == 401 and response.headers.get('X-GitHub-OTP') and response.headers.get('X-GitHub-OTP').startswith('required')): two_factor_code = None while not two_factor_code: two_factor_code = prompt_pass(msg='Enter your two factor authentication code: ') print('') headers = {'Content-Type': 'application/json' + '; charset=utf-8', 'Accept': 'application/json', 'Authorization': basic_auth, 'X-GitHub-OTP': two_factor_code} response = self.post_authorization_request(headers=headers, body=request_body) import json response_json = json.loads(response.content) if response.status_code == 200 or response.status_code == 201: logger.warning('Created new personal access token with scopes (admin:repo_hook, repo, user). Name: %s ' 'You can revoke this from your GitHub settings if the pipeline is no longer required.', note) self.token = response_json['token'] else: raise CLIError('Could not create a Personal Access Token for GitHub. Check your credentials and try again.')
def credential_set(token=None, team_instance=None): """Set the credential (PAT) to use for a particular account :param token: PAT token for the VSTS account or your TFS project collection. If not supplied, you will be prompted for your token. :type token: str :param team_instance: The URI for the VSTS account (https://<account>.visualstudio.com) or your TFS project collection. :type team_instance: str """ disable_command_version_checking() if token is None: try: token = prompt_pass('Token: ', confirm=False, help_string="The token (PAT) to authenticate with.") except NoTTYException: raise CLIError('The token argument needs to be set when run in a non-interactive mode.') if team_instance is not None: team_instance = get_base_url(team_instance) logger.info("Creating connection with personal access token.") credentials = BasicAuthentication('', token) connection = _get_vss_connection(team_instance, credentials) location_client = connection.get_client('vsts.location.v4_1.location_client.LocationClient') try: location_client.get_connection_data() except Exception as ex2: logger.debug(ex2, exc_info=True) raise ValueError("Failed to authenticate using the supplied token.") set_credential(team_instance=team_instance, token=token)
def sqlvm_group_update(instance, domain_fqdn=None, cluster_operator_account=None, sql_service_account=None, storage_account_url=None, storage_account_key=None, cluster_bootstrap_account=None, file_share_witness_path=None, ou_path=None, tags=None): ''' Updates a SQL virtual machine group. ''' if domain_fqdn is not None: instance.wsfc_domain_profile.domain_fqdn = domain_fqdn if cluster_operator_account is not None: instance.wsfc_domain_profile.cluster_operator_account = cluster_operator_account if cluster_bootstrap_account is not None: instance.wsfc_domain_profile.cluster_bootstrap_account = cluster_bootstrap_account if sql_service_account is not None: instance.wsfc_domain_profile.sql_service_account = sql_service_account if storage_account_url is not None: instance.wsfc_domain_profile.storage_account_url = storage_account_url if storage_account_key is not None: instance.wsfc_domain_profile.storage_access_key = storage_account_key if storage_account_url and not storage_account_key: instance.wsfc_domain_profile.storage_access_key = prompt_pass('Storage Key: ', confirm=True) if file_share_witness_path is not None: instance.wsfc_domain_profile.file_share_witness_path = file_share_witness_path if ou_path is not None: instance.wsfc_domain_profile.ou_path = ou_path if tags is not None: instance.tags = tags return instance
def create_github_service_endpoint(name, github_url, organization=None, project=None, detect=None): """ Create a GitHub service endpoint. :param name: Name of service endpoint to create :type name: str :param github_url: Url for github for creating service endpoint :type github_url: str :rtype: :class:`ServiceEndpoint <service_endpoint.v4_1.models.ServiceEndpoint>` """ organization, project = resolve_instance_and_project( detect=detect, organization=organization, project=project) client = get_service_endpoint_client(organization) if AZ_DEVOPS_GITHUB_PAT_ENVKEY not in os.environ: error_message = 'Please pass GitHub access token in ' + AZ_DEVOPS_GITHUB_PAT_ENVKEY +\ ' environment variable in non-interactive mode.' verify_is_a_tty_or_raise_error(error_message) github_access_token = prompt_pass('GitHub access token:', confirm=True) else: logger.debug('Picking GitHub PAT from environment variable') github_access_token = os.environ[AZ_DEVOPS_GITHUB_PAT_ENVKEY] service_endpoint_authorization = EndpointAuthorization( parameters={'accessToken': github_access_token}, scheme=SERVICE_ENDPOINT_AUTHORIZATION_PERSONAL_ACCESS_TOKEN) service_endpoint_to_create = ServiceEndpoint( authorization=service_endpoint_authorization, name=name, type=SERVICE_ENDPOINT_TYPE_GITHUB, url=github_url) return client.create_service_endpoint(service_endpoint_to_create, project)
def create_connection(connection_info_json, prompt_prefix, typeOfInfo): user_name = connection_info_json.get('userName', None) or prompt(prompt_prefix + 'Username: '******'password', None) or prompt_pass(msg=prompt_prefix + 'Password: '******'serverName', None) if "mysql" in typeOfInfo: port = connection_info_json.get('port', 3306) return MySqlConnectionInfo(user_name=user_name, password=password, server_name=server_name, port=port) elif "postgres" in typeOfInfo: database_name = connection_info_json.get('databaseName', "postgres") port = connection_info_json.get('port', 5432) return PostgreSqlConnectionInfo(user_name=user_name, password=password, server_name=server_name, database_name=database_name, port=port) elif "mongo" in typeOfInfo: connection_string = connection_info_json['connectionString'] # Strip out the username and password from the connection string (if they exist) to store them securely. rex_conn_string = re.compile(r'^(mongodb://|mongodb\+srv://|http://|https://)(.*:.*@)?(.*)') connection_string_match = rex_conn_string.search(connection_string) connection_string = connection_string_match.group(1) + connection_string_match.group(3) if connection_string_match.group(2) is not None and not user_name and not password: rex_un_pw = re.compile('^(.*):(.*)@') un_pw_match = rex_un_pw.search(connection_string_match.group(2)) user_name = un_pw_match.group(1) password = un_pw_match.group(2) return MongoDbConnectionInfo(connection_string=connection_string, user_name=user_name, password=password) else: # If no match, Pass the connection info through return connection_info_json
def _create_azure_file_volume(azure_file_volume_share_name, azure_file_volume_account_name, azure_file_volume_account_key): """Create Azure File volume. """ azure_file_volume = None if azure_file_volume_share_name: if not azure_file_volume_account_name: raise CLIError( 'Please specify --azure-file-volume-account-name in order to use Azure File volume.' ) if not azure_file_volume_account_key: try: azure_file_volume_account_key = prompt_pass( msg='Azure File storage account key: ') except NoTTYException: raise CLIError( 'Please specify --azure-file-volume-account-key in order to use Azure File volume.' ) azure_file_volume = AzureFileVolume( share_name=azure_file_volume_share_name, storage_account_name=azure_file_volume_account_name, storage_account_key=azure_file_volume_account_key) return Volume(name=AZURE_FILE_VOLUME_NAME, azure_file=azure_file_volume) if azure_file_volume else None
def password_validator(ns): if not ns.administrator_login_password: try: ns.administrator_login_password = prompt_pass( msg='Admin Password: '******'Please specify password in non-interactive mode.')
def _prompt_repair_password(namespace): from knack.prompting import prompt_pass, NoTTYException try: namespace.repair_password = prompt_pass('Repair VM admin password: '******'Please specify password in non-interactive mode.')
def sqlvm_group_create(client, cmd, sql_virtual_machine_group_name, resource_group_name, sql_image_offer, sql_image_sku, domain_fqdn, cluster_operator_account, sql_service_account, storage_account_url, storage_account_key=None, location=None, cluster_bootstrap_account=None, file_share_witness_path=None, ou_path=None, tags=None): ''' Creates a SQL virtual machine group. ''' tags = tags or {} if not storage_account_key: storage_account_key = prompt_pass('Storage Key: ', confirm=True) # Create the windows server failover cluster domain profile object. wsfc_domain_profile_object = WsfcDomainProfile(domain_fqdn=domain_fqdn, ou_path=ou_path, cluster_bootstrap_account=cluster_bootstrap_account, cluster_operator_account=cluster_operator_account, sql_service_account=sql_service_account, file_share_witness_path=file_share_witness_path, storage_account_url=storage_account_url, storage_account_primary_key=storage_account_key) sqlvm_group_object = SqlVirtualMachineGroup(sql_image_offer=sql_image_offer, sql_image_sku=sql_image_sku, wsfc_domain_profile=wsfc_domain_profile_object, location=location, tags=tags) # Since it's a running operation, we will do the put and then the get to display the instance. LongRunningOperation(cmd.cli_ctx)(sdk_no_wait(False, client.create_or_update, resource_group_name, sql_virtual_machine_group_name, sqlvm_group_object)) return client.get(resource_group_name, sql_virtual_machine_group_name)
def create_connection(connection_info_json, prompt_prefix, typeOfInfo): typeOfInfo = typeOfInfo.lower() user_name = connection_info_json.get( 'userName', None) or prompt(prompt_prefix + 'Username: '******'password', None) or prompt_pass(msg=prompt_prefix + 'Password: '******'serverName', None) if "mysql" in typeOfInfo: port = connection_info_json.get('port', 3306) return MySqlConnectionInfo(user_name=user_name, password=password, server_name=server_name, port=port) elif "postgre" in typeOfInfo: database_name = connection_info_json.get('databaseName', "postgres") port = connection_info_json.get('port', 5432) return PostgreSqlConnectionInfo(user_name=user_name, password=password, server_name=server_name, database_name=database_name, port=port) data_source = connection_info_json.get('dataSource', None) authentication = connection_info_json.get('authentication', None) encrypt_connection = connection_info_json.get('encryptConnection', None) trust_server_certificate = connection_info_json.get( 'trustServerCertificate', None) additional_settings = connection_info_json.get('additionalSettings', None) return SqlConnectionInfo(user_name=user_name, password=password, data_source=data_source, authentication=authentication, encrypt_connection=encrypt_connection, trust_server_certificate=trust_server_certificate, additional_settings=additional_settings)
def _config_env_public_azure(cli_ctx, _): from adal.adal_error import AdalError from azure.cli.core.commands.client_factory import get_mgmt_service_client from azure.cli.core._profile import Profile from azure.cli.core.profiles import ResourceType # Determine if user logged in try: list( get_mgmt_service_client( cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES).resources.list()) except CLIError: # Not logged in login_successful = False while not login_successful: method_index = prompt_choice_list(MSG_PROMPT_LOGIN, LOGIN_METHOD_LIST) answers['login_index'] = method_index answers['login_options'] = str(LOGIN_METHOD_LIST) profile = Profile(cli_ctx=cli_ctx) interactive = False username = None password = None service_principal = None tenant = None if method_index == 0: # device auth interactive = True elif method_index == 1: # username and password username = prompt('Username: '******'Password: '******'Service principal: ') tenant = prompt('Tenant: ') password = prompt_pass(msg='Client secret: ') elif method_index == 3: # skip return try: profile.find_subscriptions_on_login(interactive, username, password, service_principal, tenant) login_successful = True logger.warning('Login successful!') except AdalError as err: logger.error('Login error!') logger.error(err)
def test_prompt_pass_question_with_help_string(self, _): my_password = '******' with mock.patch('getpass.getpass', side_effect=['?', my_password]): with mock.patch('sys.stdout', new_callable=StringIO) as mock_stdout: actual_result = prompt_pass(help_string='Anything you want!') self.assertEqual(my_password, actual_result) self.assertIn('Anything you want!', mock_stdout.getvalue())
def get_upload_oci_driver_input(task_options_json): driver_path = task_options_json.get('ociDriverPath', None) user_name = task_options_json.get('userName', None) or prompt('Share Path Username: '******'password', None) or prompt_pass(msg='Share Path Password: ') return UploadOCIDriverTaskInput(driver_share=FileShare( path=driver_path, user_name=user_name, password=password))
def validate_authentication_type(namespace, formula=None): if formula and formula.formula_content: if formula.formula_content.is_authentication_with_ssh_key is True: namespace.authentication_type = 'ssh' namespace.ssh_key = formula.formula_content.ssh_key elif formula.formula_content.is_authentication_with_ssh_key is False: namespace.admin_username = formula.formula_content.user_name namespace.admin_password = formula.formula_content.password namespace.authentication_type = 'password' # validate proper arguments supplied based on the authentication type if namespace.authentication_type == 'password': password_usage_error = "incorrect usage for authentication-type 'password': "******"[--admin-username USERNAME] --admin-password PASSWORD | " \ "[--admin-username USERNAME] --saved-secret SECRETNAME" if namespace.ssh_key or namespace.generate_ssh_keys or ( namespace.saved_secret and namespace.admin_password): raise ValueError(password_usage_error) # Respect user's provided saved secret name for password authentication if namespace.saved_secret: namespace.admin_password = "******".format(namespace.saved_secret) if not namespace.admin_password: # prompt for admin password if not supplied from knack.prompting import prompt_pass, NoTTYException try: namespace.admin_password = prompt_pass('Admin Password: '******'Please specify both username and password in non-interactive mode.' ) elif namespace.authentication_type == 'ssh': if namespace.os_type != 'Linux': raise CLIError( "incorrect authentication-type '{}' for os type '{}'".format( namespace.authentication_type, namespace.os_type)) ssh_usage_error = "incorrect usage for authentication-type 'ssh': " \ "[--admin-username USERNAME] | " \ "[--admin-username USERNAME] --ssh-key KEY | " \ "[--admin-username USERNAME] --generate-ssh-keys | " \ "[--admin-username USERNAME] --saved-secret SECRETNAME" if namespace.admin_password or (namespace.saved_secret and (namespace.ssh_key or namespace.generate_ssh_keys)): raise ValueError(ssh_usage_error) # Respect user's provided saved secret name for ssh authentication if namespace.saved_secret: namespace.ssh_key = "[[{}]]".format(namespace.saved_secret) else: validate_ssh_key(namespace) else: raise CLIError("incorrect value for authentication-type: {}".format( namespace.authentication_type))
def login(cmd, username=None, password=None, service_principal=None, tenant=None, allow_no_subscriptions=False, identity=False, identity_port=None): """Log in to access Azure subscriptions""" from adal.adal_error import AdalError import requests # quick argument usage check if (any([password, service_principal, tenant, allow_no_subscriptions]) and identity): raise CLIError("usage error: '--identity' is not applicable with other arguments") if identity_port: logger.warning("'--identity-port' is no longer required to login using managed identity." " This flag will be removed in a future release of CLI.") interactive = False profile = Profile(cli_ctx=cmd.cli_ctx, async_persist=False) if identity: if in_cloud_console(): return profile.find_subscriptions_in_cloud_console() return profile.find_subscriptions_in_vm_with_msi(username) elif in_cloud_console(): # tell users they might not need login logger.warning(_CLOUD_CONSOLE_LOGIN_WARNING) if username: if not password: try: password = prompt_pass('Password: '******'Please specify both username and password in non-interactive mode.') else: interactive = True try: subscriptions = profile.find_subscriptions_on_login( interactive, username, password, service_principal, tenant, allow_no_subscriptions=allow_no_subscriptions) except AdalError as err: # try polish unfriendly server errors if username: msg = str(err) suggestion = "For cross-check, try 'az login' to authenticate through browser." if ('ID3242:' in msg) or ('Server returned an unknown AccountType' in msg): raise CLIError("The user name might be invalid. " + suggestion) if 'Server returned error in RSTR - ErrorCode' in msg: raise CLIError("Logging in through command line is not supported. " + suggestion) raise CLIError(err) except requests.exceptions.ConnectionError as err: raise CLIError('Please ensure you have network connection. Error detail: ' + str(err)) all_subscriptions = list(subscriptions) for sub in all_subscriptions: sub['cloudName'] = sub.pop('environmentName', None) return all_subscriptions
def _config_env_public_azure(cli_ctx, _): from adal.adal_error import AdalError from azure.cli.core.commands.client_factory import get_mgmt_service_client from azure.mgmt.resource import ResourceManagementClient from azure.cli.core._profile import Profile # Determine if user logged in try: list(get_mgmt_service_client(cli_ctx, ResourceManagementClient).resources.list()) except CLIError: # Not logged in login_successful = False while not login_successful: method_index = prompt_choice_list(MSG_PROMPT_LOGIN, LOGIN_METHOD_LIST) answers['login_index'] = method_index answers['login_options'] = str(LOGIN_METHOD_LIST) profile = Profile(cli_ctx=cli_ctx) interactive = False username = None password = None service_principal = None tenant = None if method_index == 0: # device auth interactive = True elif method_index == 1: # username and password username = prompt('Username: '******'Password: '******'Service principal: ') tenant = prompt('Tenant: ') password = prompt_pass(msg='Client secret: ') elif method_index == 3: # skip return try: profile.find_subscriptions_on_login( interactive, username, password, service_principal, tenant) login_successful = True logger.warning('Login successful!') except AdalError as err: logger.error('Login error!') logger.error(err)
def login(cmd, username=None, password=None, service_principal=None, tenant=None, allow_no_subscriptions=False, identity=False, use_device_code=False): """Log in to access Azure subscriptions""" from adal.adal_error import AdalError import requests # quick argument usage check if any([password, service_principal, tenant, allow_no_subscriptions]) and identity: raise CLIError("usage error: '--identity' is not applicable with other arguments") if any([password, service_principal, username, identity]) and use_device_code: raise CLIError("usage error: '--use-device-code' is not applicable with other arguments") interactive = False profile = Profile(cli_ctx=cmd.cli_ctx, async_persist=False) if identity: if in_cloud_console(): return profile.find_subscriptions_in_cloud_console() return profile.find_subscriptions_in_vm_with_msi(username) elif in_cloud_console(): # tell users they might not need login logger.warning(_CLOUD_CONSOLE_LOGIN_WARNING) if username: if not password: try: password = prompt_pass('Password: '******'Please specify both username and password in non-interactive mode.') else: interactive = True try: subscriptions = profile.find_subscriptions_on_login( interactive, username, password, service_principal, tenant, use_device_code=use_device_code, allow_no_subscriptions=allow_no_subscriptions) except AdalError as err: # try polish unfriendly server errors if username: msg = str(err) suggestion = "For cross-check, try 'az login' to authenticate through browser." if ('ID3242:' in msg) or ('Server returned an unknown AccountType' in msg): raise CLIError("The user name might be invalid. " + suggestion) if 'Server returned error in RSTR - ErrorCode' in msg: raise CLIError("Logging in through command line is not supported. " + suggestion) raise CLIError(err) except requests.exceptions.ConnectionError as err: raise CLIError('Please ensure you have network connection. Error detail: ' + str(err)) all_subscriptions = list(subscriptions) for sub in all_subscriptions: sub['cloudName'] = sub.pop('environmentName', None) return all_subscriptions
def create_sql_connection_info(connection_info_json, prompt_prefix): return SqlConnectionInfo( user_name=connection_info_json.get('userName', None) or prompt(prompt_prefix + 'Username: '******'password', None) or prompt_pass(msg=prompt_prefix + 'Password: '******'dataSource', None), authentication=connection_info_json.get('authentication', None), encrypt_connection=connection_info_json.get('encryptConnection', None), trust_server_certificate=connection_info_json.get('trustServerCertificate', None), additional_settings=connection_info_json.get('additionalSettings', None))
def _load_key(key_filename): pkey = None try: pkey = paramiko.RSAKey.from_private_key_file(key_filename, None) except paramiko.PasswordRequiredException: key_pass = prompt_pass('Password for private key:') pkey = paramiko.RSAKey.from_private_key_file(key_filename, key_pass) if pkey is None: raise CLIError('failed to load key: {}'.format(key_filename)) return pkey
def _get_pat_token(): try: token = prompt_pass( 'Token: ', confirm=False, help_string="The token (PAT) to authenticate with.") except NoTTYException: logger.info("Getting PAT token in non-interactive mode.") token = sys.stdin.readline().rstrip() return token
def _create_image_registry_credentials(registry_login_server, registry_username, registry_password, image): """Create image registry credentials. """ image_registry_credentials = None if registry_login_server: if not registry_username: raise CLIError('Please specify --registry-username in order to use custom image registry.') if not registry_password: try: registry_password = prompt_pass(msg='Image registry password: '******'Please specify --registry-password in order to use custom image registry.') image_registry_credentials = [ImageRegistryCredential(server=registry_login_server, username=registry_username, password=registry_password)] elif ACR_SERVER_DELIMITER in image.split("/")[0]: if not registry_username: try: registry_username = prompt(msg='Image registry username: '******'Please specify --registry-username in order to use Azure Container Registry.') if not registry_password: try: registry_password = prompt_pass(msg='Image registry password: '******'Please specify --registry-password in order to use Azure Container Registry.') acr_server = image.split("/")[0] if image.split("/") else None if acr_server: image_registry_credentials = [ImageRegistryCredential(server=acr_server, username=registry_username, password=registry_password)] elif registry_username and registry_password and SERVER_DELIMITER in image.split("/")[0]: login_server = image.split("/")[0] if image.split("/") else None if login_server: image_registry_credentials = [ImageRegistryCredential(server=login_server, username=registry_username, password=registry_password)] else: raise CLIError('Failed to parse login server from image name; please explicitly specify --registry-server.') return image_registry_credentials
def test_prompt_pass_confirm_invalid_then_valid(self, _): my_password1 = '7ndBkS3zKQazD5N3zzstubZq' my_password2 = 'LTQ9haNMCSGp8p2uQHw2K9xf' with mock.patch('getpass.getpass', side_effect=[ my_password1, my_password2, my_password2, my_password2 ]): with mock.patch('logging.Logger.warning') as mock_log_warn: actual_result = prompt_pass(confirm=True) mock_log_warn.assert_called_once_with(_INVALID_PASSWORD_MSG) self.assertEqual(my_password2, actual_result)
def _get_value_from_env_or_stdin(var_name): env_var_name = AZ_DEVOPS_PIPELINES_VARIABLES_KEY_PREFIX + var_name logger.debug('Checking for variable %s in environment variable %s', var_name, env_var_name) import os value = os.getenv(env_var_name, None) logger.debug('Value of Variable %s in environment variable is found %s', var_name, value is not None) if not value: verify_is_a_tty_or_raise_error( 'For non-interactive consoles set environment variable {}, or pipe the value of variable into the command.' .format(env_var_name)) value = prompt_pass(msg=var_name + ': ') return value
def login(cmd, username=None, password=None, service_principal=None, tenant=None, allow_no_subscriptions=False, identity=False, use_device_code=False, use_cert_sn_issuer=None, scopes=None, client_assertion=None): """Log in to access Azure subscriptions""" # quick argument usage check if any([password, service_principal, tenant]) and identity: raise CLIError("usage error: '--identity' is not applicable with other arguments") if any([password, service_principal, username, identity]) and use_device_code: raise CLIError("usage error: '--use-device-code' is not applicable with other arguments") if use_cert_sn_issuer and not service_principal: raise CLIError("usage error: '--use-sn-issuer' is only applicable with a service principal") if service_principal and not username: raise CLIError('usage error: --service-principal --username NAME --password SECRET --tenant TENANT') interactive = False profile = Profile(cli_ctx=cmd.cli_ctx) if identity: if in_cloud_console(): return profile.login_in_cloud_shell() return profile.login_with_managed_identity(username, allow_no_subscriptions) if in_cloud_console(): # tell users they might not need login logger.warning(_CLOUD_CONSOLE_LOGIN_WARNING) if username: if not (password or client_assertion): try: password = prompt_pass('Password: '******'Please specify both username and password in non-interactive mode.') else: interactive = True if service_principal: from azure.cli.core.auth.identity import ServicePrincipalAuth password = ServicePrincipalAuth.build_credential(password, client_assertion, use_cert_sn_issuer) subscriptions = profile.login( interactive, username, password, service_principal, tenant, scopes=scopes, use_device_code=use_device_code, allow_no_subscriptions=allow_no_subscriptions, use_cert_sn_issuer=use_cert_sn_issuer) all_subscriptions = list(subscriptions) for sub in all_subscriptions: sub['cloudName'] = sub.pop('environmentName', None) return all_subscriptions
def update_adla_catalog_credential(client, account_name, database_name, credential_name, credential_user_name, uri, credential_user_password=None, new_credential_user_password=None): from azure.mgmt.datalake.analytics.catalog.models import DataLakeAnalyticsCatalogCredentialUpdateParameters if not credential_user_password: try: credential_user_password = prompt_pass('Current Password:'******'Please specify --user-name --password and --new-password in non-interactive mode.') if not new_credential_user_password: try: new_credential_user_password = prompt_pass('New Password:'******'Please specify --user-name --password and --new-password in non-interactive mode.') update_params = DataLakeAnalyticsCatalogCredentialUpdateParameters(credential_user_password, new_credential_user_password, uri, credential_user_name) client.update_credential(account_name, database_name, credential_name, update_params)
def _get_pat_token(): try: token = prompt_pass( 'Token: ', confirm=False, help_string="The token (PAT) to authenticate with.") while len(token) <= 1: logger.warning('Please provide a PAT token.') logger.warning( 'If you are using CTRL + V to paste the token, it won\'t work ' 'on windows command prompt or powershell - ' 'https://github.com/microsoft/knack/issues/160.') logger.warning( 'Use right click or console menu to paste the token.') token = prompt_pass( 'Token: ', confirm=False, help_string="The token (PAT) to authenticate with.") except NoTTYException: logger.info("Getting PAT token in non-interactive mode.") token = sys.stdin.readline().rstrip() return token
def validate_authentication_type(namespace, formula=None): if formula and formula.formula_content: if formula.formula_content.is_authentication_with_ssh_key is True: namespace.authentication_type = 'ssh' namespace.ssh_key = formula.formula_content.ssh_key elif formula.formula_content.is_authentication_with_ssh_key is False: namespace.admin_username = formula.formula_content.user_name namespace.admin_password = formula.formula_content.password namespace.authentication_type = 'password' # validate proper arguments supplied based on the authentication type if namespace.authentication_type == 'password': password_usage_error = "incorrect usage for authentication-type 'password': "******"[--admin-username USERNAME] --admin-password PASSWORD | " \ "[--admin-username USERNAME] --saved-secret SECRETNAME" if namespace.ssh_key or namespace.generate_ssh_keys or (namespace.saved_secret and namespace.admin_password): raise ValueError(password_usage_error) # Respect user's provided saved secret name for password authentication if namespace.saved_secret: namespace.admin_password = "******".format(namespace.saved_secret) if not namespace.admin_password: # prompt for admin password if not supplied from knack.prompting import prompt_pass, NoTTYException try: namespace.admin_password = prompt_pass('Admin Password: '******'Please specify both username and password in non-interactive mode.') elif namespace.authentication_type == 'ssh': if namespace.os_type != 'Linux': raise CLIError("incorrect authentication-type '{}' for os type '{}'".format( namespace.authentication_type, namespace.os_type)) ssh_usage_error = "incorrect usage for authentication-type 'ssh': " \ "[--admin-username USERNAME] | " \ "[--admin-username USERNAME] --ssh-key KEY | " \ "[--admin-username USERNAME] --generate-ssh-keys | " \ "[--admin-username USERNAME] --saved-secret SECRETNAME" if namespace.admin_password or (namespace.saved_secret and (namespace.ssh_key or namespace.generate_ssh_keys)): raise ValueError(ssh_usage_error) # Respect user's provided saved secret name for ssh authentication if namespace.saved_secret: namespace.ssh_key = "[[{}]]".format(namespace.saved_secret) else: validate_ssh_key(namespace) else: raise CLIError("incorrect value for authentication-type: {}".format(namespace.authentication_type))
def _create_azure_file_volume(azure_file_volume_share_name, azure_file_volume_account_name, azure_file_volume_account_key): """Create Azure File volume. """ azure_file_volume = None if azure_file_volume_share_name: if not azure_file_volume_account_name: raise CLIError('Please specify --azure-file-volume-account-name in order to use Azure File volume.') if not azure_file_volume_account_key: try: azure_file_volume_account_key = prompt_pass(msg='Azure File storage account key: ') except NoTTYException: raise CLIError('Please specify --azure-file-volume-account-key in order to use Azure File volume.') azure_file_volume = AzureFileVolume(share_name=azure_file_volume_share_name, storage_account_name=azure_file_volume_account_name, storage_account_key=azure_file_volume_account_key) return Volume(name=AZURE_FILE_VOLUME_NAME, azure_file=azure_file_volume) if azure_file_volume else None
def create_connection(connection_info_json, prompt_prefix, typeOfInfo): user_name = connection_info_json.get( 'userName', None) or prompt(prompt_prefix + 'Username: '******'password', None) or prompt_pass(msg=prompt_prefix + 'Password: '******'serverName', None) if "mysql" in typeOfInfo: port = connection_info_json.get('port', 3306) return MySqlConnectionInfo(user_name=user_name, password=password, server_name=server_name, port=port) database_name = connection_info_json.get('databaseName', "postgres") port = connection_info_json.get('port', 5432) return PostgreSqlConnectionInfo(user_name=user_name, password=password, server_name=server_name, database_name=database_name, port=port)
def create_adla_catalog_credential(client, account_name, database_name, credential_name, credential_user_name, uri, credential_user_password=None): if not credential_user_password: try: credential_user_password = prompt_pass('Password:'******'Please specify both --user-name and --password in non-interactive mode.' ) create_params = DataLakeAnalyticsCatalogCredentialCreateParameters( credential_user_password, uri, credential_user_name) client.create_credential(account_name, database_name, credential_name, create_params)
def _prompt_for_parameters(missing_parameters, fail_on_no_tty=True): # pylint: disable=too-many-statements prompt_list = missing_parameters.keys() if isinstance(missing_parameters, OrderedDict) \ else sorted(missing_parameters) result = OrderedDict() no_tty = False for param_name in prompt_list: param = missing_parameters[param_name] param_type = param.get('type', 'string') description = 'Missing description' metadata = param.get('metadata', None) if metadata is not None: description = metadata.get('description', description) allowed_values = param.get('allowedValues', None) prompt_str = "Please provide {} value for '{}' (? for help): ".format(param_type, param_name) while True: if allowed_values is not None: try: ix = prompt_choice_list(prompt_str, allowed_values, help_string=description) result[param_name] = allowed_values[ix] except NoTTYException: result[param_name] = None no_tty = True break elif param_type == 'securestring': try: value = prompt_pass(prompt_str, help_string=description) except NoTTYException: value = None no_tty = True result[param_name] = value break elif param_type == 'int': try: int_value = prompt_int(prompt_str, help_string=description) result[param_name] = int_value except NoTTYException: result[param_name] = 0 no_tty = True break elif param_type == 'bool': try: value = prompt_t_f(prompt_str, help_string=description) result[param_name] = value except NoTTYException: result[param_name] = False no_tty = True break elif param_type in ['object', 'array']: try: value = prompt(prompt_str, help_string=description) except NoTTYException: value = '' no_tty = True if value == '': value = {} if param_type == 'object' else [] else: try: value = shell_safe_json_parse(value) except Exception as ex: # pylint: disable=broad-except logger.error(ex) continue result[param_name] = value break else: try: result[param_name] = prompt(prompt_str, help_string=description) except NoTTYException: result[param_name] = None no_tty = True break if no_tty and fail_on_no_tty: raise NoTTYException return result
def password_validator(ns): if not ns.administrator_login_password: try: ns.administrator_login_password = prompt_pass(msg='Admin Password: '******'Please specify password in non-interactive mode.')
def sqlvm_update(instance, sql_server_license_type=None, enable_auto_patching=None, day_of_week=None, maintenance_window_starting_hour=None, maintenance_window_duration=None, enable_auto_backup=None, enable_encryption=False, retention_period=None, storage_account_url=None, storage_access_key=None, backup_password=None, backup_system_dbs=False, backup_schedule_type=None, full_backup_frequency=None, full_backup_start_time=None, full_backup_window_hours=None, log_backup_frequency=None, enable_key_vault_credential=None, credential_name=None, azure_key_vault_url=None, service_principal_name=None, service_principal_secret=None, connectivity_type=None, port=None, sql_workload_type=None, enable_r_services=None, tags=None): ''' Updates a SQL virtual machine. ''' if tags is not None: instance.tags = tags if sql_server_license_type is not None: instance.sql_server_license_type = sql_server_license_type if (enable_auto_patching is not None or day_of_week is not None or maintenance_window_starting_hour is not None or maintenance_window_duration is not None): enable_auto_patching = enable_auto_patching if enable_auto_patching is False else True instance.auto_patching_settings = AutoPatchingSettings(enable=enable_auto_patching, day_of_week=day_of_week, maintenance_window_starting_hour=maintenance_window_starting_hour, maintenance_window_duration=maintenance_window_duration) if (enable_auto_backup is not None or enable_encryption or retention_period is not None or storage_account_url is not None or storage_access_key is not None or backup_password is not None or backup_system_dbs or backup_schedule_type is not None or full_backup_frequency is not None or full_backup_start_time is not None or full_backup_window_hours is not None or log_backup_frequency is not None): enable_auto_backup = enable_auto_backup if enable_auto_backup is False else True if not storage_access_key: storage_access_key = prompt_pass('Storage Key: ', confirm=True) if enable_encryption and not backup_password: backup_password = prompt_pass('Backup Password: '******'Service Principal Secret: ', confirm=True) instance.key_vault_credential_settings = KeyVaultCredentialSettings(enable=enable_key_vault_credential, credential_name=credential_name, service_principal_name=service_principal_name, service_principal_secret=service_principal_secret, azure_key_vault_url=azure_key_vault_url) instance.server_configurations_management_settings = ServerConfigurationsManagementSettings() if (connectivity_type is not None or port is not None): instance.server_configurations_management_settings.sql_connectivity_update_settings = SqlConnectivityUpdateSettings(connectivity_type=connectivity_type, port=port) if sql_workload_type is not None: instance.server_configurations_management_settings.sql_workload_type_update_settings = SqlWorkloadTypeUpdateSettings(sql_workload_type=sql_workload_type) if enable_r_services is not None: instance.server_configurations_management_settings.additional_features_server_configurations = AdditionalFeaturesServerConfigurations(is_rservices_enabled=enable_r_services) # If none of the settings was modified, reset server_configurations_management_settings to be null if (instance.server_configurations_management_settings.sql_connectivity_update_settings is None and instance.server_configurations_management_settings.sql_workload_type_update_settings is None and instance.server_configurations_management_settings.sql_storage_update_settings is None and instance.server_configurations_management_settings.additional_features_server_configurations is None): instance.server_configurations_management_settings = None return instance
def _get_credentials(cli_ctx, registry_name, resource_group_name, username, password, only_refresh_token, repository=None, artifact_repository=None, permission=None): """Try to get AAD authorization tokens or admin user credentials. :param str registry_name: The name of container registry :param str resource_group_name: The name of resource group :param str username: The username used to log into the container registry :param str password: The password used to log into the container registry :param bool only_refresh_token: Whether to ask for only refresh token, or for both refresh and access tokens :param str repository: Repository for which the access token is requested :param str artifact_repository: Artifact repository for which the access token is requested :param str permission: The requested permission on the repository, '*' or 'pull' """ # 1. if username was specified, verify that password was also specified if username: # Try to use the pre-defined login server suffix to construct login server from registry name. # This is to avoid a management server request if username/password are already provided. # In all other cases, including the suffix not defined, login server will be obtained from server. login_server_suffix = get_login_server_suffix(cli_ctx) if login_server_suffix: login_server = '{}{}'.format(registry_name, login_server_suffix) else: registry, _ = get_registry_by_name(cli_ctx, registry_name, resource_group_name) login_server = registry.login_server if not password: try: password = prompt_pass(msg='Password: '******'Please specify both username and password in non-interactive mode.') return login_server, username, password registry, resource_group_name = get_registry_by_name(cli_ctx, registry_name, resource_group_name) login_server = registry.login_server # 2. if we don't yet have credentials, attempt to get a refresh token if not password and registry.sku.name in MANAGED_REGISTRY_SKU: try: password = _get_aad_token( cli_ctx, login_server, only_refresh_token, repository, artifact_repository, permission) return login_server, EMPTY_GUID, password except CLIError as e: logger.warning("Unable to get AAD authorization tokens with message: %s", str(e)) # 3. if we still don't have credentials, attempt to get the admin credentials (if enabled) if not password and registry.admin_user_enabled: try: cred = cf_acr_registries(cli_ctx).list_credentials(resource_group_name, registry_name) username = cred.username password = cred.passwords[0].value return login_server, username, password except CLIError as e: logger.warning("Unable to get admin user credentials with message: %s", str(e)) # 4. if we still don't have credentials, prompt the user if not password: try: username = prompt('Username: '******'Password: '******'Unable to authenticate using AAD or admin login credentials. ' + 'Please specify both username and password in non-interactive mode.') return login_server, None, None
def _get_credentials(cmd, # pylint: disable=too-many-statements registry_name, tenant_suffix, username, password, only_refresh_token, repository=None, artifact_repository=None, permission=None): """Try to get AAD authorization tokens or admin user credentials. :param str registry_name: The name of container registry :param str tenant_suffix: The registry login server tenant suffix :param str username: The username used to log into the container registry :param str password: The password used to log into the container registry :param bool only_refresh_token: Whether to ask for only refresh token, or for both refresh and access tokens :param str repository: Repository for which the access token is requested :param str artifact_repository: Artifact repository for which the access token is requested :param str permission: The requested permission on the repository, '*' or 'pull' """ # Raise an error if password is specified but username isn't if not username and password: raise CLIError('Please also specify username if password is specified.') cli_ctx = cmd.cli_ctx resource_not_found, registry = None, None try: registry, resource_group_name = get_registry_by_name(cli_ctx, registry_name) login_server = registry.login_server if tenant_suffix: logger.warning( "Obtained registry login server '%s' from service. The specified suffix '%s' is ignored.", login_server, tenant_suffix) except (ResourceNotFound, CLIError) as e: resource_not_found = str(e) logger.debug("Could not get registry from service. Exception: %s", resource_not_found) if not isinstance(e, ResourceNotFound) and _AZ_LOGIN_MESSAGE not in resource_not_found: raise # Try to use the pre-defined login server suffix to construct login server from registry name. login_server_suffix = get_login_server_suffix(cli_ctx) if not login_server_suffix: raise login_server = '{}{}{}'.format( registry_name, '-{}'.format(tenant_suffix) if tenant_suffix else '', login_server_suffix).lower() # Validate the login server is reachable url = 'https://' + login_server + '/v2/' try: challenge = requests.get(url, verify=(not should_disable_connection_verify())) if challenge.status_code in [403]: raise CLIError("Looks like you don't have access to registry '{}'. " "Are firewalls and virtual networks enabled?".format(login_server)) except RequestException as e: logger.debug("Could not connect to registry login server. Exception: %s", str(e)) if resource_not_found: logger.warning("%s\nUsing '%s' as the default registry login server.", resource_not_found, login_server) raise CLIError("Could not connect to the registry login server '{}'. ".format(login_server) + "Please verify that the registry exists and " + "the URL '{}' is reachable from your environment.".format(url)) # 1. if username was specified, verify that password was also specified if username: if not password: try: password = prompt_pass(msg='Password: '******'Please specify both username and password in non-interactive mode.') return login_server, username, password # 2. if we don't yet have credentials, attempt to get a refresh token if not registry or registry.sku.name in get_managed_sku(cmd): try: return login_server, EMPTY_GUID, _get_aad_token( cli_ctx, login_server, only_refresh_token, repository, artifact_repository, permission) except CLIError as e: logger.warning("%s: %s", AAD_TOKEN_BASE_ERROR_MESSAGE, str(e)) # 3. if we still don't have credentials, attempt to get the admin credentials (if enabled) if registry: if registry.admin_user_enabled: try: cred = cf_acr_registries(cli_ctx).list_credentials(resource_group_name, registry_name) return login_server, cred.username, cred.passwords[0].value except CLIError as e: logger.warning("%s: %s", ADMIN_USER_BASE_ERROR_MESSAGE, str(e)) else: logger.warning("%s: %s", ADMIN_USER_BASE_ERROR_MESSAGE, "Admin user is disabled.") else: logger.warning("%s: %s", ADMIN_USER_BASE_ERROR_MESSAGE, resource_not_found) # 4. if we still don't have credentials, prompt the user try: username = prompt('Username: '******'Password: '******'Unable to authenticate using AAD or admin login credentials. ' + 'Please specify both username and password in non-interactive mode.') return login_server, None, None