Ejemplo n.º 1
0
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))
Ejemplo n.º 2
0
 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)))
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
 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)
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
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))
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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))
Ejemplo n.º 10
0
 def create_service_principal(self, app_id):
     return self.client.service_principals.create(
         ServicePrincipalCreateParameters(app_id=app_id, ))
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
    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)