def create_service_principal(cli_ctx, identifier, resolve_app=True, rbac_client=None): if rbac_client is None: rbac_client = get_graph_rbac_management_client(cli_ctx) if resolve_app: try: uuid.UUID(identifier) result = list( rbac_client.applications.list( filter="appId eq '{}'".format(identifier))) except ValueError: result = list( rbac_client.applications.list( filter="identifierUris/any(s:s eq '{}')".format( identifier))) if not result: # assume we get an object id result = [rbac_client.applications.get(identifier)] app_id = result[0].app_id else: app_id = identifier return rbac_client.service_principals.create( ServicePrincipalCreateParameters(app_id=app_id, account_enabled=True))
def __createServicePrincipal(self): if self.getServicePrincipalId() == None: log.info("Creating service principal for appId " + self.__appId) servicePrincipalCreateParameters = ServicePrincipalCreateParameters( self.__appId, True, None) return self.getGraphRbacClient().service_principals.create( servicePrincipalCreateParameters)
def create_resource(self): try: client = self.get_graphrbac_client(self.tenant) response = client.service_principals.create(ServicePrincipalCreateParameters(app_id=self.app_id, account_enabled=True)) self.results['changed'] = True self.results.update(self.to_dict(response)) return response except GraphErrorException as ge: self.fail("Error creating service principle, app id {0} - {1}".format(self.app_id, str(ge)))
def create_aad_user(credentials, tenant_id, **kwargs): """ Create an AAD application and service principal :param credentials: msrestazure.azure_active_directory.AdalAuthentication :param tenant_id: str :param **application_name: str """ graph_rbac_client = GraphRbacManagementClient( credentials, tenant_id, base_url=AZURE_PUBLIC_CLOUD.endpoints.active_directory_graph_resource_id) application_credential = uuid.uuid4() try: display_name = kwargs.get("application_name", DefaultSettings.application_name) application = graph_rbac_client.applications.create( parameters=ApplicationCreateParameters( available_to_other_tenants=False, identifier_uris=["http://{}.com".format(display_name)], display_name=display_name, password_credentials=[ PasswordCredential( start_date=datetime(2000, 1, 1, 0, 0, 0, 0, tzinfo=timezone.utc), end_date=datetime(2299, 12, 31, 0, 0, 0, 0, tzinfo=timezone.utc), value=application_credential, key_id=uuid.uuid4()) ])) service_principal = graph_rbac_client.service_principals.create( ServicePrincipalCreateParameters(app_id=application.app_id, account_enabled=True)) except GraphErrorException as e: if e.inner_exception.code == "Request_BadRequest": application = next( graph_rbac_client.applications.list( filter="identifierUris/any(c:c eq 'http://{}.com')".format(display_name))) confirmation_prompt = "Previously created application with name {} found. "\ "Would you like to use it? (y/n): ".format(application.display_name) prompt_for_confirmation(confirmation_prompt, e, ValueError("Response not recognized. Please try again.")) password_credentials = list( graph_rbac_client.applications.list_password_credentials(application_object_id=application.object_id)) password_credentials.append( PasswordCredential( start_date=datetime(2000, 1, 1, 0, 0, 0, 0, tzinfo=timezone.utc), end_date=datetime(2299, 12, 31, 0, 0, 0, 0, tzinfo=timezone.utc), value=application_credential, key_id=uuid.uuid4())) graph_rbac_client.applications.patch( application_object_id=application.object_id, parameters=ApplicationUpdateParameters(password_credentials=password_credentials)) service_principal = next( graph_rbac_client.service_principals.list(filter="appId eq '{}'".format(application.app_id))) else: raise e return application.app_id, service_principal.object_id, str(application_credential)
def create_service_principal(self, app_id): max_retries = 3 retries = 0 while True: try: return self.client.service_principals.create( ServicePrincipalCreateParameters(app_id=app_id)) except GraphErrorException as ex: if retries >= max_retries: raise retries += 1 logger.warning("%s; retry %d of %d", ex, retries, max_retries) time.sleep(10)
def _create_service_principal(identifier, retain_raw_response=False): client = _graph_client_factory() try: uuid.UUID(identifier) result = list(client.applications.list(filter="appId eq '{}'".format(identifier))) except ValueError: result = list(client.applications.list( filter="identifierUris/any(s:s eq '{}')".format(identifier))) if not result: #assume we get an object id result = [client.applications.get(identifier)] app_id = result[0].app_id return client.service_principals.create(ServicePrincipalCreateParameters(app_id, True), raw=retain_raw_response)
def create_service_principal(identifier, resolve_app=True, client=None): if client is None: client = _graph_client_factory() if resolve_app: try: uuid.UUID(identifier) result = list(client.applications.list(filter="appId eq '{}'".format(identifier))) except ValueError: result = list(client.applications.list( filter="identifierUris/any(s:s eq '{}')".format(identifier))) if not result: # assume we get an object id result = [client.applications.get(identifier)] app_id = result[0].app_id else: app_id = identifier return client.service_principals.create(ServicePrincipalCreateParameters(app_id, True))
def _create_service_principal( graph_client, name, app_id): _RETRY_TIMES = 36 # retry till server replication is done for l in range(0, _RETRY_TIMES): try: aad_sp = graph_client.service_principals.create(ServicePrincipalCreateParameters(app_id=app_id, account_enabled=True)) 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 return aad_sp.object_id
def _create_service_principal(cli_ctx, identifier, resolve_app=True): client = _graph_client_factory(cli_ctx) if resolve_app: if _is_guid(identifier): result = list( client.applications.list( filter="appId eq '{}'".format(identifier))) else: result = list( client.applications.list( filter="identifierUris/any(s:s eq '{}')".format( identifier))) if not result: # assume we get an object id result = [client.applications.get(identifier)] app_id = result[0].app_id else: app_id = identifier return client.service_principals.create( ServicePrincipalCreateParameters(app_id, True))
def create_service_principal(self, app_id): return self.client.service_principals.create( ServicePrincipalCreateParameters(app_id=app_id, ))
def setup_rbac(self) -> None: """ Setup the client application for the OneFuzz instance. By default, Service Principals do not have access to create client applications in AAD. """ if self.results["client_id"] and self.results["client_secret"]: logger.info("using existing client application") return client = get_client_from_cli_profile( GraphRbacManagementClient, subscription_id=self.get_subscription_id()) logger.info("checking if RBAC already exists") try: existing = list( client.applications.list(filter="displayName eq '%s'" % self.application_name)) except GraphErrorException: logger.error( "unable to query RBAC. Provide client_id and client_secret") sys.exit(1) app_roles = [ AppRole( allowed_member_types=["Application"], display_name=OnefuzzAppRole.CliClient.value, id=str(uuid.uuid4()), is_enabled=True, description="Allows access from the CLI.", value=OnefuzzAppRole.CliClient.value, ), AppRole( allowed_member_types=["Application"], display_name=OnefuzzAppRole.ManagedNode.value, id=str(uuid.uuid4()), is_enabled=True, description="Allow access from a lab machine.", value=OnefuzzAppRole.ManagedNode.value, ), ] app: Optional[Application] = None if not existing: logger.info("creating Application registration") if self.multi_tenant_domain: url = "https://%s/%s" % ( self.multi_tenant_domain, self.application_name, ) else: url = "https://%s.azurewebsites.net" % self.application_name params = ApplicationCreateParameters( display_name=self.application_name, identifier_uris=[url], reply_urls=[url + "/.auth/login/aad/callback"], optional_claims=OptionalClaims(id_token=[], access_token=[]), required_resource_access=[ RequiredResourceAccess( resource_access=[ ResourceAccess(id=USER_IMPERSONATION, type="Scope") ], resource_app_id="00000002-0000-0000-c000-000000000000", ) ], app_roles=app_roles, ) app = client.applications.create(params) logger.info("creating service principal") service_principal_params = ServicePrincipalCreateParameters( account_enabled=True, app_role_assignment_required=False, service_principal_type="Application", app_id=app.app_id, ) def try_sp_create() -> None: error: Optional[Exception] = None for _ in range(10): try: client.service_principals.create( service_principal_params) return except GraphErrorException as err: # work around timing issue when creating service principal # https://github.com/Azure/azure-cli/issues/14767 if ("service principal being created must in the local tenant" not in str(err)): raise err logging.warning( "creating service principal failed with an error that occurs " "due to AAD race conditions") time.sleep(60) if error is None: raise Exception("service principal creation failed") else: raise error try_sp_create() else: app = existing[0] existing_role_values = [ app_role.value for app_role in app.app_roles ] has_missing_roles = any( [role.value not in existing_role_values for role in app_roles]) if has_missing_roles: # disabling the existing app role first to allow the update # this is a requirement to update the application roles for role in app.app_roles: role.is_enabled = False client.applications.patch( app.object_id, ApplicationUpdateParameters(app_roles=app.app_roles)) # overriding the list of app roles client.applications.patch( app.object_id, ApplicationUpdateParameters(app_roles=app_roles)) if self.multi_tenant_domain and app.sign_in_audience == "AzureADMyOrg": url = "https://%s/%s" % ( self.multi_tenant_domain, self.application_name, ) client.applications.patch( app.object_id, ApplicationUpdateParameters(identifier_uris=[url])) set_app_audience(app.object_id, "AzureADMultipleOrgs") elif (not self.multi_tenant_domain and app.sign_in_audience == "AzureADMultipleOrgs"): set_app_audience(app.object_id, "AzureADMyOrg") url = "https://%s.azurewebsites.net" % self.application_name client.applications.patch( app.object_id, ApplicationUpdateParameters(identifier_uris=[url])) else: logger.debug("No change to App Registration signInAudence setting") creds = list( client.applications.list_password_credentials(app.object_id)) client.applications.update_password_credentials( app.object_id, creds) (password_id, password) = self.create_password(app.object_id) cli_app = list( client.applications.list(filter="appId eq '%s'" % ONEFUZZ_CLI_APP)) if len(cli_app) == 0: logger.info( "Could not find the default CLI application under the current " "subscription, creating a new one") app_info = register_application( "onefuzz-cli", self.application_name, OnefuzzAppRole.CliClient, self.get_subscription_id(), ) if self.multi_tenant_domain: authority = COMMON_AUTHORITY else: authority = app_info.authority self.cli_config = { "client_id": app_info.client_id, "authority": authority, } else: authorize_application(uuid.UUID(ONEFUZZ_CLI_APP), app.app_id) self.results["client_id"] = app.app_id self.results["client_secret"] = password # Log `client_secret` for consumption by CI. if self.log_service_principal: logger.info("client_id: %s client_secret: %s", app.app_id, password) else: logger.debug("client_id: %s client_secret: %s", app.app_id, password)
def setup_rbac(self): """ Setup the client application for the OneFuzz instance. By default, Service Principals do not have access to create client applications in AAD. """ if self.results["client_id"] and self.results["client_secret"]: logger.info("using existing client application") return client = get_client_from_cli_profile(GraphRbacManagementClient) logger.info("checking if RBAC already exists") try: existing = list( client.applications.list( filter="displayName eq '%s'" % self.application_name ) ) except GraphErrorException: logger.error("unable to query RBAC. Provide client_id and client_secret") sys.exit(1) app_roles = [ AppRole( allowed_member_types=["Application"], display_name="CliClient", id=str(uuid.uuid4()), is_enabled=True, description="Allows access from the CLI.", value="CliClient", ), AppRole( allowed_member_types=["Application"], display_name="ManagedNode", id=str(uuid.uuid4()), is_enabled=True, description="Allow access from a lab machine.", value="ManagedNode", ), ] if not existing: logger.info("creating Application registration") url = "https://%s.azurewebsites.net" % self.application_name params = ApplicationCreateParameters( display_name=self.application_name, identifier_uris=[url], reply_urls=[url + "/.auth/login/aad/callback"], optional_claims=OptionalClaims(id_token=[], access_token=[]), required_resource_access=[ RequiredResourceAccess( resource_access=[ ResourceAccess(id=USER_IMPERSONATION, type="Scope") ], resource_app_id="00000002-0000-0000-c000-000000000000", ) ], app_roles=app_roles, ) app = client.applications.create(params) logger.info("creating service principal") service_principal_params = ServicePrincipalCreateParameters( account_enabled=True, app_role_assignment_required=False, service_principal_type="Application", app_id=app.app_id, ) client.service_principals.create(service_principal_params) else: app: Application = existing[0] existing_role_values = [app_role.value for app_role in app.app_roles] has_missing_roles = any( [role.value not in existing_role_values for role in app_roles] ) if has_missing_roles: # disabling the existing app role first to allow the update # this is a requirement to update the application roles for role in app.app_roles: role.is_enabled = False client.applications.patch( app.object_id, ApplicationUpdateParameters(app_roles=app.app_roles) ) # overriding the list of app roles client.applications.patch( app.object_id, ApplicationUpdateParameters(app_roles=app_roles) ) creds = list(client.applications.list_password_credentials(app.object_id)) client.applications.update_password_credentials(app.object_id, creds) (password_id, password) = self.create_password(app.object_id) onefuzz_cli_app_uuid = uuid.UUID(ONEFUZZ_CLI_APP) cli_app = get_application(onefuzz_cli_app_uuid) if cli_app is None: logger.info( "Could not find the default CLI application under the current " "subscription, creating a new one" ) app_info = register_application("onefuzz-cli", self.application_name) self.cli_config = { "client_id": app_info.client_id, "authority": app_info.authority, } else: authorize_application(onefuzz_cli_app_uuid, app.app_id) self.results["client_id"] = app.app_id self.results["client_secret"] = password # Log `client_secret` for consumption by CI. if self.log_service_principal: logger.info("client_id: %s client_secret: %s", app.app_id, password) else: logger.debug("client_id: %s client_secret: %s", app.app_id, password)