コード例 #1
0
    def test_get_expanded_subscription_info(self):
        storage_mock = {'subscriptions': None}
        profile = Profile(storage_mock)

        consolidated = Profile._normalize_properties(self.user1,
                                                     [self.subscription1],
                                                     False)
        profile._set_subscriptions(consolidated)
        sub_id = self.id1.split('/')[-1]

        #testing dump of existing logged in account
        extended_info = profile.get_expanded_subscription_info()
        self.assertEqual(self.user1, extended_info['userName'])
        self.assertEqual(sub_id, extended_info['subscriptionId'])
        self.assertEqual(self.display_name1, extended_info['subscriptionName'])
        self.assertEqual('https://login.microsoftonline.com',
                         extended_info['endpoints'].active_directory)

        #testing dump of service principal by 'create-for-rbac'
        extended_info = profile.get_expanded_subscription_info(
            name='great-sp', password='******')
        self.assertEqual(sub_id, extended_info['subscriptionId'])
        self.assertEqual(self.display_name1, extended_info['subscriptionName'])
        self.assertEqual('great-sp', extended_info['client'])
        self.assertEqual('https://login.microsoftonline.com',
                         extended_info['endpoints'].active_directory)
コード例 #2
0
ファイル: test_profile.py プロジェクト: Azure/azure-cli
    def test_get_expanded_subscription_info(self):
        storage_mock = {'subscriptions': None}
        profile = Profile(storage_mock)

        consolidated = Profile._normalize_properties(self.user1,
                                                     [self.subscription1],
                                                     False)
        profile._set_subscriptions(consolidated)
        sub_id = self.id1.split('/')[-1]

        #testing dump of existing logged in account
        extended_info = profile.get_expanded_subscription_info()
        self.assertEqual(self.user1, extended_info['userName'])
        self.assertEqual(sub_id, extended_info['subscriptionId'])
        self.assertEqual(self.display_name1, extended_info['subscriptionName'])
        self.assertEqual('https://login.microsoftonline.com',
                         extended_info['endpoints'].active_directory)

        #testing dump of service principal by 'create-for-rbac'
        extended_info = profile.get_expanded_subscription_info(name='great-sp',
                                                               password='******')
        self.assertEqual(sub_id, extended_info['subscriptionId'])
        self.assertEqual(self.display_name1, extended_info['subscriptionName'])
        self.assertEqual('great-sp', extended_info['client'])
        self.assertEqual('https://login.microsoftonline.com',
                         extended_info['endpoints'].active_directory)
コード例 #3
0
    def test_get_expanded_subscription_info_for_logged_in_service_principal(self,
                                                                            mock_auth_context):
        mock_auth_context.acquire_token_with_client_credentials.return_value = self.token_entry1
        mock_arm_client = mock.MagicMock()
        mock_arm_client.subscriptions.list.return_value = [self.subscription1]
        finder = SubscriptionFinder(lambda _, _2: mock_auth_context,
                                    None,
                                    lambda _: mock_arm_client)

        storage_mock = {'subscriptions': []}
        profile = Profile(storage_mock, use_global_creds_cache=False)
        profile._management_resource_uri = 'https://management.core.windows.net/'
        profile.find_subscriptions_on_login(False,
                                            '1234',
                                            'my-secret',
                                            True,
                                            self.tenant_id,
                                            False,
                                            finder)
        # action
        extended_info = profile.get_expanded_subscription_info()
        # assert
        self.assertEqual(self.id1.split('/')[-1], extended_info['subscriptionId'])
        self.assertEqual(self.display_name1, extended_info['subscriptionName'])
        self.assertEqual('1234', extended_info['client'])
        self.assertEqual('https://login.microsoftonline.com',
                         extended_info['endpoints'].active_directory)
コード例 #4
0
    def test_get_expanded_subscription_info_for_logged_in_service_principal(self,
                                                                            mock_auth_context):
        mock_auth_context.acquire_token_with_client_credentials.return_value = self.token_entry1
        mock_arm_client = mock.MagicMock()
        mock_arm_client.subscriptions.list.return_value = [self.subscription1]
        finder = SubscriptionFinder(lambda _, _2: mock_auth_context,
                                    None,
                                    lambda _: mock_arm_client)

        storage_mock = {'subscriptions': []}
        profile = Profile(storage_mock, use_global_creds_cache=False)
        profile._management_resource_uri = 'https://management.core.windows.net/'
        profile.find_subscriptions_on_login(False,
                                            '1234',
                                            'my-secret',
                                            True,
                                            self.tenant_id,
                                            False,
                                            finder)
        # action
        extended_info = profile.get_expanded_subscription_info()
        # assert
        self.assertEqual(self.id1.split('/')[-1], extended_info['subscriptionId'])
        self.assertEqual(self.display_name1, extended_info['subscriptionName'])
        self.assertEqual('1234', extended_info['client'])
        self.assertEqual('https://login.microsoftonline.com',
                         extended_info['endpoints'].active_directory)
コード例 #5
0
ファイル: custom.py プロジェクト: akshaysngupta/azure-cli
def show_subscription(subscription=None, expanded_view=None):
    profile = Profile()
    if not expanded_view:
        return profile.get_subscription(subscription)

    logger.warning("'--expanded-view' is deprecating and will be removed in a future release. You can get the same "
                   "information using 'az cloud show'")
    return profile.get_expanded_subscription_info(subscription)
コード例 #6
0
ファイル: custom.py プロジェクト: xscript/azure-cli
def show_subscription(subscription=None, expanded_view=None):
    profile = Profile()
    if not expanded_view:
        return profile.get_subscription(subscription)

    logger.warning(
        "'--expanded-view' is deprecating and will be removed in a future release. You can get the same "
        "information using 'az cloud show'")
    return profile.get_expanded_subscription_info(subscription)
コード例 #7
0
ファイル: custom.py プロジェクト: andymoe/azure-cli
def create_service_principal_for_rbac(name=None, password=None, years=1, #pylint:disable=too-many-arguments
                                      scopes=None, role=None, expanded_view=None):
    '''create a service principal that can access or modify resources
    :param str name: an unique uri. If missing, the command will generate one.
    :param str password: the password used to login. If missing, command will generate one.
    :param str years: Years the password will be valid.
    :param str scopes: space separated scopes the service principal's role assignment applies to.
    :param str role: role the service principal has on the resources. only use with 'resource-ids'.
    '''
    if bool(scopes) != bool(role):
        raise CLIError("'--scopes' and '--role' must be used together.")
    client = _graph_client_factory()
    start_date = datetime.datetime.utcnow()
    app_display_name = 'azure-cli-' + start_date.strftime('%Y-%m-%d-%H-%M-%S')
    if name is None:
        name = 'http://' + app_display_name # just a valid uri, no need to exist

    end_date = start_date + relativedelta(years=years)
    password = password or str(uuid.uuid4())
    aad_application = create_application(client.applications, display_name=app_display_name, #pylint: disable=too-many-function-args
                                         homepage='http://'+app_display_name,
                                         identifier_uris=[name],
                                         available_to_other_tenants=False,
                                         password=password,
                                         start_date=start_date,
                                         end_date=end_date)
    #pylint: disable=no-member
    aad_sp = _create_service_principal(aad_application.app_id, bool(scopes))
    oid = aad_sp.output.object_id if scopes else aad_sp.object_id

    if scopes:
        #It is possible the SP has not been propagated to all servers, so creating assignments
        #might fail. The reliable workaround is to call out the server where creation occurred.
        #pylint: disable=protected-access
        session_key = aad_sp.response.headers._store['ocp-aad-session-key'][1]
        for scope in scopes:
            _create_role_assignment(role, oid, None, scope, ocp_aad_session_key=session_key)

    if expanded_view:
        from azure.cli.core._profile import Profile
        profile = Profile()
        result = profile.get_expanded_subscription_info(scopes[0].split('/')[2] if scopes else None,
                                                        aad_application.app_id, password)
    else:
        result = {
            'appId': aad_application.app_id,
            'password': password,
            'name': name,
            'tenant': client.config.tenant_id
            }
    return result
コード例 #8
0
ファイル: custom.py プロジェクト: Azure/azure-cli
def create_service_principal_for_rbac(name=None, password=None, years=1, #pylint:disable=too-many-arguments
                                      scopes=None, role=None, expanded_view=None):
    '''create a service principal that can access or modify resources
    :param str name: an unique uri. If missing, the command will generate one.
    :param str password: the password used to login. If missing, command will generate one.
    :param str years: Years the password will be valid.
    :param str scopes: space separated scopes the service principal's role assignment applies to.
    :param str role: role the service principal has on the resources. only use with 'resource-ids'.
    '''
    if bool(scopes) != bool(role):
        raise CLIError("'--scopes' and '--role' must be used together.")
    client = _graph_client_factory()
    start_date = datetime.datetime.now()
    app_display_name = 'azure-cli-' + start_date.strftime('%Y-%m-%d-%H-%M-%S')
    if name is None:
        name = 'http://' + app_display_name # just a valid uri, no need to exist

    end_date = start_date + relativedelta(years=years)
    password = password or str(uuid.uuid4())
    aad_application = create_application(client.applications, display_name=app_display_name, #pylint: disable=too-many-function-args
                                         homepage='http://'+app_display_name,
                                         identifier_uris=[name],
                                         available_to_other_tenants=False,
                                         password=password,
                                         start_date=start_date,
                                         end_date=end_date)
    #pylint: disable=no-member
    aad_sp = _create_service_principal(aad_application.app_id, bool(scopes))
    oid = aad_sp.output.object_id if scopes else aad_sp.object_id

    if scopes:
        #It is possible the SP has not been propagated to all servers, so creating assignments
        #might fail. The reliable workaround is to call out the server where creation occurred.
        #pylint: disable=protected-access
        session_key = aad_sp.response.headers._store['ocp-aad-session-key'][1]
        for scope in scopes:
            _create_role_assignment(role, oid, None, scope, ocp_aad_session_key=session_key)

    if expanded_view:
        from azure.cli.core._profile import Profile
        profile = Profile()
        result = profile.get_expanded_subscription_info(scopes[0].split('/')[2] if scopes else None,
                                                        aad_application.app_id, password)
    else:
        result = {
            'appId': aad_application.app_id,
            'password': password,
            'name': name,
            'tenant': client.config.tenant_id
            }
    return result
コード例 #9
0
ファイル: custom.py プロジェクト: jaczhan/azure-cli
def create_service_principal_for_rbac(
        # pylint:disable=too-many-statements,too-many-locals, too-many-branches
        name=None, password=None, years=None,
        create_cert=False, cert=None,
        scopes=None, role='Contributor',
        expanded_view=None, skip_assignment=False, keyvault=None):
    import time
    import pytz

    graph_client = _graph_client_factory()
    role_client = _auth_client_factory().role_assignments
    scopes = scopes or ['/subscriptions/' + role_client.config.subscription_id]
    years = years or 1
    sp_oid = None
    _RETRY_TIMES = 36

    app_display_name = None
    if name and '://' not in name:
        app_display_name = name
        name = "http://" + name  # normalize be a valid graph service principal name

    if name:
        query_exp = 'servicePrincipalNames/any(x:x eq \'{}\')'.format(name)
        aad_sps = list(graph_client.service_principals.list(filter=query_exp))
        if aad_sps:
            raise CLIError("'{}' already exists.".format(name))

    app_start_date = datetime.datetime.now(pytz.utc)
    app_end_date = app_start_date + relativedelta(years=years or 1)

    app_display_name = app_display_name or ('azure-cli-' +
                                            app_start_date.strftime('%Y-%m-%d-%H-%M-%S'))
    if name is None:
        name = 'http://' + app_display_name  # just a valid uri, no need to exist

    password, public_cert_string, cert_file, cert_start_date, cert_end_date = \
        _process_service_principal_creds(years, app_start_date, app_end_date, cert, create_cert,
                                         password, keyvault)

    app_start_date, app_end_date, cert_start_date, cert_end_date = \
        _validate_app_dates(app_start_date, app_end_date, cert_start_date, cert_end_date)

    aad_application = create_application(graph_client.applications,
                                         display_name=app_display_name,
                                         homepage='http://' + app_display_name,
                                         identifier_uris=[name],
                                         available_to_other_tenants=False,
                                         password=password,
                                         key_value=public_cert_string,
                                         start_date=app_start_date,
                                         end_date=app_end_date)
    # pylint: disable=no-member
    app_id = aad_application.app_id
    # retry till server replication is done
    for l in range(0, _RETRY_TIMES):
        try:
            aad_sp = _create_service_principal(app_id, resolve_app=False)
            break
        except Exception as ex:  # pylint: disable=broad-except
            # pylint: disable=line-too-long
            if l < _RETRY_TIMES and (
                    ' does not reference ' in str(ex) or ' does not exist ' in str(ex)):
                time.sleep(5)
                logger.warning('Retrying service principal creation: %s/%s', l + 1, _RETRY_TIMES)
            else:
                logger.warning(
                    "Creating service principal failed for appid '%s'. Trace followed:\n%s",
                    name, ex.response.headers if hasattr(ex,
                                                         'response') else ex)  # pylint: disable=no-member
                raise
    sp_oid = aad_sp.object_id

    # retry while server replication is done
    if not skip_assignment:
        # pylint: disable=line-too-long
        for scope in scopes:
            for l in range(0, _RETRY_TIMES):
                try:
                    _create_role_assignment(role, sp_oid, None, scope, resolve_assignee=False)
                    break
                except Exception as ex:
                    if l < _RETRY_TIMES and ' does not exist in the directory ' in str(ex):
                        time.sleep(5)
                        logger.warning('Retrying role assignment creation: %s/%s', l + 1,
                                       _RETRY_TIMES)
                        continue
                    else:
                        # dump out history for diagnoses
                        logger.warning('Role assignment creation failed.\n')
                        if getattr(ex, 'response', None) is not None:
                            logger.warning('role assignment response headers: %s\n',
                                           ex.response.headers)  # pylint: disable=no-member
                    raise

    if expanded_view:
        logger.warning("'--expanded-view' is deprecating and will be removed in a future release. "
                       "You can get the same information using 'az cloud show'")
        from azure.cli.core._profile import Profile
        profile = Profile()
        result = profile.get_expanded_subscription_info(scopes[0].split('/')[2] if scopes else None,
                                                        app_id, password)
    else:
        result = {
            'appId': app_id,
            'password': password,
            'name': name,
            'displayName': app_display_name,
            'tenant': graph_client.config.tenant_id
        }
        if cert_file:
            # pylint: disable=line-too-long
            logger.warning(
                "Please copy %s to a safe place. When run 'az login' provide the file path to the --password argument",
                cert_file)
            result['fileWithCertAndPrivateKey'] = cert_file
    return result
コード例 #10
0
ファイル: custom.py プロジェクト: johnkemnetz/azure-cli
def create_service_principal_for_rbac(name=None, password=None, years=1, #pylint:disable=too-many-arguments,too-many-statements,too-many-locals, too-many-branches
                                      create_cert=False, cert=None,
                                      scopes=None, role='Contributor',
                                      expanded_view=None, skip_assignment=False):
    '''create a service principal and configure its access to Azure resources
    :param str name: a display name or an app id uri. Command will generate one if missing.
    :param str password: the password used to login. If missing, command will generate one.
    :param str cert: PEM formatted public certificate. Do not include private key info.
    :param str years: Years the password will be valid.
    :param str scopes: space separated scopes the service principal's role assignment applies to.
           Defaults to the root of the current subscription.
    :param str role: role the service principal has on the resources.
    '''
    import time
    graph_client = _graph_client_factory()
    role_client = _auth_client_factory().role_assignments
    scopes = scopes or ['/subscriptions/' + role_client.config.subscription_id]
    sp_oid = None
    _RETRY_TIMES = 36

    app_display_name = None
    if name and not '://' in name:
        app_display_name = name
        name = "http://" + name #normalize be a valid graph service principal name

    if name:
        query_exp = 'servicePrincipalNames/any(x:x eq \'{}\')'.format(name)
        aad_sps = list(graph_client.service_principals.list(filter=query_exp))
        if aad_sps:
            raise CLIError("'{}' already exists.".format(name))

    #pylint: disable=protected-access
    public_cert_string = None
    cert_file = None
    password = None

    if len([x for x in [cert, create_cert, password] if x]) > 1:
        raise CLIError('Usage error: --cert | --create-cert | --password')
    if create_cert:
        public_cert_string, cert_file = _create_self_signed_cert(years)
    elif cert:
        public_cert_string = cert
    else:
        password = password or str(uuid.uuid4())

    start_date = datetime.datetime.utcnow()
    app_display_name = app_display_name or ('azure-cli-' +
                                            start_date.strftime('%Y-%m-%d-%H-%M-%S'))
    if name is None:
        name = 'http://' + app_display_name # just a valid uri, no need to exist

    end_date = start_date + relativedelta(years=years)

    aad_application = create_application(graph_client.applications,
                                         display_name=app_display_name, #pylint: disable=too-many-function-args
                                         homepage='http://'+app_display_name,
                                         identifier_uris=[name],
                                         available_to_other_tenants=False,
                                         password=password,
                                         key_value=public_cert_string,
                                         start_date=start_date,
                                         end_date=end_date)
    #pylint: disable=no-member
    app_id = aad_application.app_id
    #retry till server replication is done
    for l in range(0, _RETRY_TIMES):
        try:
            aad_sp = _create_service_principal(app_id, resolve_app=False)
            break
        except Exception as ex: #pylint: disable=broad-except
            #pylint: disable=line-too-long
            if l < _RETRY_TIMES and 'The appId of the service principal does not reference a valid application object' in str(ex):
                time.sleep(5)
                logger.warning('Retrying service principal creation: %s/%s', l+1, _RETRY_TIMES)
            else:
                logger.warning("Creating service principal failed for appid '%s'. Trace followed:\n%s",
                               name, ex.response.headers if hasattr(ex, 'response') else ex) #pylint: disable=no-member
                raise
    sp_oid = aad_sp.object_id

    #retry while server replication is done
    if not skip_assignment:
        # pylint: disable=line-too-long
        for scope in scopes:
            for l in range(0, _RETRY_TIMES):
                try:
                    _create_role_assignment(role, sp_oid, None, scope, resolve_assignee=False)
                    break
                except Exception as ex:
                    if l < _RETRY_TIMES and ' does not exist in the directory ' in str(ex):
                        time.sleep(5)
                        logger.warning('Retrying role assignment creation: %s/%s', l+1, _RETRY_TIMES)
                        continue
                    else:
                        #dump out history for diagnoses
                        logger.warning('Role assignment creation failed.\n')
                        if getattr(ex, 'response', None) is not None:
                            logger.warning('role assignment response headers: %s\n', ex.response.headers) #pylint: disable=no-member
                    raise

    if expanded_view:
        from azure.cli.core._profile import Profile
        profile = Profile()
        result = profile.get_expanded_subscription_info(scopes[0].split('/')[2] if scopes else None,
                                                        app_id, password)
    else:
        result = {
            'appId': app_id,
            'password': password,
            'name': name,
            'displayName': app_display_name,
            'tenant': graph_client.config.tenant_id
            }
        if cert_file:
            # pylint: disable=line-too-long
            logger.warning("Please copy %s to a safe place. When run 'az login' provide the file path to the --password argument", cert_file)
            result['fileWithCertAndPrivateKey'] = cert_file
    return result
コード例 #11
0
ファイル: custom.py プロジェクト: batizza/azure-cli
def show_subscription(subscription=None, expanded_view=None):
    profile = Profile()
    if not expanded_view:
        return profile.get_subscription(subscription)
    else:
        return profile.get_expanded_subscription_info(subscription)
コード例 #12
0
def show_subscription(subscription=None, expanded_view=None):
    profile = Profile()
    if not expanded_view:
        return profile.get_subscription(subscription)
    else:
        return profile.get_expanded_subscription_info(subscription)
コード例 #13
0
def create_service_principal_for_rbac(
        # pylint:disable=too-many-arguments,too-many-statements,too-many-locals, too-many-branches
        name=None, password=None, years=1,
        create_cert=False, cert=None,
        scopes=None, role='Contributor',
        expanded_view=None, skip_assignment=False):
    '''create a service principal and configure its access to Azure resources
    :param str name: a display name or an app id uri. Command will generate one if missing.
    :param str password: the password used to login. If missing, command will generate one.
    :param str cert: PEM formatted public certificate. Do not include private key info.
    :param str years: Years the password will be valid.
    :param str scopes: space separated scopes the service principal's role assignment applies to.
           Defaults to the root of the current subscription.
    :param str role: role the service principal has on the resources.
    '''
    import time
    graph_client = _graph_client_factory()
    role_client = _auth_client_factory().role_assignments
    scopes = scopes or ['/subscriptions/' + role_client.config.subscription_id]
    sp_oid = None
    _RETRY_TIMES = 36

    app_display_name = None
    if name and '://' not in name:
        app_display_name = name
        name = "http://" + name  # normalize be a valid graph service principal name

    if name:
        query_exp = 'servicePrincipalNames/any(x:x eq \'{}\')'.format(name)
        aad_sps = list(graph_client.service_principals.list(filter=query_exp))
        if aad_sps:
            raise CLIError("'{}' already exists.".format(name))

    # pylint: disable=protected-access
    public_cert_string = None
    cert_file = None

    if len([x for x in [cert, create_cert, password] if x]) > 1:
        raise CLIError('Usage error: --cert | --create-cert | --password')
    if create_cert:
        public_cert_string, cert_file = _create_self_signed_cert(years)
    elif cert:
        public_cert_string = cert
    else:
        password = password or str(uuid.uuid4())

    start_date = datetime.datetime.utcnow()
    app_display_name = app_display_name or ('azure-cli-' +
                                            start_date.strftime('%Y-%m-%d-%H-%M-%S'))
    if name is None:
        name = 'http://' + app_display_name  # just a valid uri, no need to exist

    end_date = start_date + relativedelta(years=years)

    aad_application = create_application(graph_client.applications,
                                         display_name=app_display_name,
                                         # pylint: disable=too-many-function-args
                                         homepage='http://' + app_display_name,
                                         identifier_uris=[name],
                                         available_to_other_tenants=False,
                                         password=password,
                                         key_value=public_cert_string,
                                         start_date=start_date,
                                         end_date=end_date)
    # pylint: disable=no-member
    app_id = aad_application.app_id
    # retry till server replication is done
    for l in range(0, _RETRY_TIMES):
        try:
            aad_sp = _create_service_principal(app_id, resolve_app=False)
            break
        except Exception as ex:  # pylint: disable=broad-except
            # pylint: disable=line-too-long
            if l < _RETRY_TIMES and (
                    ' does not reference ' in str(ex) or ' does not exist ' in str(ex)):
                time.sleep(5)
                logger.warning('Retrying service principal creation: %s/%s', l + 1, _RETRY_TIMES)
            else:
                logger.warning(
                    "Creating service principal failed for appid '%s'. Trace followed:\n%s",
                    name, ex.response.headers if hasattr(ex,
                                                         'response') else ex)  # pylint: disable=no-member
                raise
    sp_oid = aad_sp.object_id

    # retry while server replication is done
    if not skip_assignment:
        # pylint: disable=line-too-long
        for scope in scopes:
            for l in range(0, _RETRY_TIMES):
                try:
                    _create_role_assignment(role, sp_oid, None, scope, resolve_assignee=False)
                    break
                except Exception as ex:
                    if l < _RETRY_TIMES and ' does not exist in the directory ' in str(ex):
                        time.sleep(5)
                        logger.warning('Retrying role assignment creation: %s/%s', l + 1,
                                       _RETRY_TIMES)
                        continue
                    else:
                        # dump out history for diagnoses
                        logger.warning('Role assignment creation failed.\n')
                        if getattr(ex, 'response', None) is not None:
                            logger.warning('role assignment response headers: %s\n',
                                           ex.response.headers)  # pylint: disable=no-member
                    raise

    if expanded_view:
        from azure.cli.core._profile import Profile
        profile = Profile()
        result = profile.get_expanded_subscription_info(scopes[0].split('/')[2] if scopes else None,
                                                        app_id, password)
    else:
        result = {
            'appId': app_id,
            'password': password,
            'name': name,
            'displayName': app_display_name,
            'tenant': graph_client.config.tenant_id
        }
        if cert_file:
            # pylint: disable=line-too-long
            logger.warning(
                "Please copy %s to a safe place. When run 'az login' provide the file path to the --password argument",
                cert_file)
            result['fileWithCertAndPrivateKey'] = cert_file
    return result
コード例 #14
0
ファイル: custom.py プロジェクト: erich-wang/azure-cli
def create_service_principal_for_rbac(name=None, password=None, years=1, #pylint:disable=too-many-arguments,too-many-statements,too-many-locals
                                      scopes=None, role='Contributor', expanded_view=None):
    '''create a service principal and configure its access to Azure resources
    :param str name: a display name or an app id uri. Command will generate one if missing.
    :param str password: the password used to login. If missing, command will generate one.
    :param str years: Years the password will be valid.
    :param str scopes: space separated scopes the service principal's role assignment applies to.
           Defaults to the root of the current subscription.
    :param str role: role the service principal has on the resources.
    '''
    import time
    graph_client = _graph_client_factory()
    role_client = _auth_client_factory().role_assignments
    scopes = scopes or ['/subscriptions/' + role_client.config.subscription_id]
    sp_oid = None
    sp_created = False
    _RETRY_TIMES = 24

    app_display_name = None
    if name and not '://' in name:
        app_display_name = name
        name = "http://" + name #normalize be a valid graph service principal name

    if name:
        query_exp = 'servicePrincipalNames/any(x:x eq \'{}\')'.format(name)
        aad_sps = list(graph_client.service_principals.list(filter=query_exp))
        if aad_sps:
            sp_oid = aad_sps[0].object_id
            app_id = aad_sps[0].app_id

    #pylint: disable=protected-access
    if not sp_oid:
        start_date = datetime.datetime.utcnow()
        app_display_name = app_display_name or ('azure-cli-' +
                                                start_date.strftime('%Y-%m-%d-%H-%M-%S'))
        if name is None:
            name = 'http://' + app_display_name # just a valid uri, no need to exist

        end_date = start_date + relativedelta(years=years)
        password = password or str(uuid.uuid4())
        aad_application = create_application(graph_client.applications,
                                             display_name=app_display_name, #pylint: disable=too-many-function-args
                                             homepage='http://'+app_display_name,
                                             identifier_uris=[name],
                                             available_to_other_tenants=False,
                                             password=password,
                                             start_date=start_date,
                                             end_date=end_date)
        #pylint: disable=no-member
        app_id = aad_application.app_id
        #retry till server replication is done
        for l in range(0, _RETRY_TIMES):
            try:
                aad_sp = _create_service_principal(app_id, resolve_app=False)
                break
            except Exception as ex: #pylint: disable=broad-except
                #pylint: disable=line-too-long
                if l < _RETRY_TIMES and 'The appId of the service principal does not reference a valid application object' in str(ex):
                    time.sleep(5)
                    logger.warning('Retrying service principal creation: %s/%s', l+1, _RETRY_TIMES)
                else:
                    logger.warning("Creating service principal failed for appid '%s'. Trace followed:\n%s",
                                   name, ex.response.headers) #pylint: disable=no-member
                    raise
        sp_oid = aad_sp.object_id
        sp_created = True

    #retry while server replication is done
    for scope in scopes:
        for l in range(0, _RETRY_TIMES):
            try:
                _create_role_assignment(role, sp_oid, None, scope, resolve_assignee=False)
                break
            except Exception as ex:
                if l < _RETRY_TIMES and ' does not exist in the directory ' in str(ex):
                    time.sleep(5)
                    logger.warning('Retrying role assignment creation: %s/%s', l+1, _RETRY_TIMES)
                    continue
                elif sp_created:
                    #dump out history for diagnoses
                    logger.warning('Role assignment creation failed. Traces followed:\n')
                    logger.warning('Service principal response: %s\n', aad_sp.response.headers)
                    if getattr(ex, 'response', None) is not None:
                        logger.warning('role assignment response: %s\n', ex.response.headers) #pylint: disable=no-member
                raise

    if expanded_view:
        from azure.cli.core._profile import Profile
        profile = Profile()
        result = profile.get_expanded_subscription_info(scopes[0].split('/')[2] if scopes else None,
                                                        app_id, password)
    else:
        result = {
            'appId': app_id,
            'password': password,
            'name': name,
            'displayName': app_display_name,
            'tenant': graph_client.config.tenant_id
            }
    return result
コード例 #15
0
ファイル: custom.py プロジェクト: akshaysngupta/azure-cli
def create_service_principal_for_rbac(
        # pylint:disable=too-many-statements,too-many-locals, too-many-branches
        name=None, password=None, years=None,
        create_cert=False, cert=None,
        scopes=None, role='Contributor',
        expanded_view=None, skip_assignment=False, keyvault=None):
    import time
    import pytz

    graph_client = _graph_client_factory()
    role_client = _auth_client_factory().role_assignments
    scopes = scopes or ['/subscriptions/' + role_client.config.subscription_id]
    years = years or 1
    sp_oid = None
    _RETRY_TIMES = 36

    app_display_name = None
    if name and '://' not in name:
        app_display_name = name
        name = "http://" + name  # normalize be a valid graph service principal name

    if name:
        query_exp = 'servicePrincipalNames/any(x:x eq \'{}\')'.format(name)
        aad_sps = list(graph_client.service_principals.list(filter=query_exp))
        if aad_sps:
            raise CLIError("'{}' already exists.".format(name))

    app_start_date = datetime.datetime.now(pytz.utc)
    app_end_date = app_start_date + relativedelta(years=years or 1)

    app_display_name = app_display_name or ('azure-cli-' +
                                            app_start_date.strftime('%Y-%m-%d-%H-%M-%S'))
    if name is None:
        name = 'http://' + app_display_name  # just a valid uri, no need to exist

    password, public_cert_string, cert_file, cert_start_date, cert_end_date = \
        _process_service_principal_creds(years, app_start_date, app_end_date, cert, create_cert,
                                         password, keyvault)

    app_start_date, app_end_date, cert_start_date, cert_end_date = \
        _validate_app_dates(app_start_date, app_end_date, cert_start_date, cert_end_date)

    aad_application = create_application(graph_client.applications,
                                         display_name=app_display_name,
                                         homepage='http://' + app_display_name,
                                         identifier_uris=[name],
                                         available_to_other_tenants=False,
                                         password=password,
                                         key_value=public_cert_string,
                                         start_date=app_start_date,
                                         end_date=app_end_date)
    # pylint: disable=no-member
    app_id = aad_application.app_id
    # retry till server replication is done
    for l in range(0, _RETRY_TIMES):
        try:
            aad_sp = _create_service_principal(app_id, resolve_app=False)
            break
        except Exception as ex:  # pylint: disable=broad-except
            if l < _RETRY_TIMES and (
                    ' does not reference ' in str(ex) or ' does not exist ' in str(ex)):
                time.sleep(5)
                logger.warning('Retrying service principal creation: %s/%s', l + 1, _RETRY_TIMES)
            else:
                logger.warning(
                    "Creating service principal failed for appid '%s'. Trace followed:\n%s",
                    name, ex.response.headers if hasattr(ex,
                                                         'response') else ex)  # pylint: disable=no-member
                raise
    sp_oid = aad_sp.object_id

    # retry while server replication is done
    if not skip_assignment:
        for scope in scopes:
            for l in range(0, _RETRY_TIMES):
                try:
                    _create_role_assignment(role, sp_oid, None, scope, resolve_assignee=False)
                    break
                except Exception as ex:
                    if l < _RETRY_TIMES and ' does not exist in the directory ' in str(ex):
                        time.sleep(5)
                        logger.warning('Retrying role assignment creation: %s/%s', l + 1,
                                       _RETRY_TIMES)
                        continue
                    else:
                        # dump out history for diagnoses
                        logger.warning('Role assignment creation failed.\n')
                        if getattr(ex, 'response', None) is not None:
                            logger.warning('role assignment response headers: %s\n',
                                           ex.response.headers)  # pylint: disable=no-member
                    raise

    if expanded_view:
        logger.warning("'--expanded-view' is deprecating and will be removed in a future release. "
                       "You can get the same information using 'az cloud show'")
        from azure.cli.core._profile import Profile
        profile = Profile()
        result = profile.get_expanded_subscription_info(scopes[0].split('/')[2] if scopes else None,
                                                        app_id, password)
    else:
        result = {
            'appId': app_id,
            'password': password,
            'name': name,
            'displayName': app_display_name,
            'tenant': graph_client.config.tenant_id
        }
        if cert_file:
            logger.warning(
                "Please copy %s to a safe place. When run 'az login' provide the file path to the --password argument",
                cert_file)
            result['fileWithCertAndPrivateKey'] = cert_file
    return result