Esempio n. 1
0
def create_application(client,
                       display_name,
                       homepage,
                       years,
                       password,
                       identifier_uris,
                       available_to_other_tenants=False,
                       reply_urls=None):
    password_credential = _build_password_credential(password, years)

    app_create_param = ApplicationCreateParameters(
        available_to_other_tenants=available_to_other_tenants,
        display_name=display_name,
        identifier_uris=identifier_uris,
        homepage=homepage,
        reply_urls=reply_urls,
        password_credentials=[password_credential])

    try:
        return client.create(app_create_param)
    except GraphErrorException as ex:
        if 'insufficient privileges' in str(ex).lower():
            link = (
                'https://docs.microsoft.com/en-us/azure/azure-resource-manager/'
                + 'resource-group-create-service-principal-portal')
            raise CLIError(
                "Directory permission is needed for the current user to register the application. "
                "For how to configure, please refer '{}'. Original error: {}".
                format(link, ex))
        raise
Esempio n. 2
0
    def create_application(self, display_name):
        password = uuid.uuid4()
        start_date = datetime.datetime.utcnow()
        end_date = datetime.datetime(2299,
                                     12,
                                     31,
                                     tzinfo=datetime.timezone.utc)

        app = self.client.applications.create(
            ApplicationCreateParameters(
                display_name=display_name,
                identifier_uris=[
                    self.MANAGED_APP_PREFIX + str(uuid.uuid4()),
                ],
                password_credentials=[
                    PasswordCredential(
                        custom_key_identifier=str(start_date).encode(),
                        start_date=start_date,
                        end_date=end_date,
                        value=password,
                    ),
                ],
            ))

        return app, password
Esempio n. 3
0
    def create_application(self, display_name):
        password = uuid.uuid4()

        try:
            end_date = datetime.datetime(2299,
                                         12,
                                         31,
                                         tzinfo=datetime.timezone.utc)
        except AttributeError:
            end_date = datetime.datetime(2299, 12, 31)

        app = self.client.applications.create(
            ApplicationCreateParameters(
                display_name=display_name,
                identifier_uris=[
                    self.MANAGED_APP_PREFIX + str(uuid.uuid4()),
                ],
                password_credentials=[
                    PasswordCredential(
                        end_date=end_date,
                        value=password,
                    ),
                ],
            ))

        return app, password
Esempio n. 4
0
def create_application(
        client,
        display_name,
        homepage,
        identifier_uris,  # pylint: disable=too-many-arguments
        available_to_other_tenants=False,
        password=None,
        reply_urls=None,
        key_value=None,
        key_type=None,
        key_usage=None,
        start_date=None,
        end_date=None):
    password_creds, key_creds = _build_application_creds(
        password, key_value, key_type, key_usage, start_date, end_date)

    app_create_param = ApplicationCreateParameters(
        available_to_other_tenants,
        display_name,
        identifier_uris,
        homepage=homepage,
        reply_urls=reply_urls,
        key_credentials=key_creds,
        password_credentials=password_creds)
    return client.create(app_create_param)
Esempio n. 5
0
def create_application(client,
                       display_name,
                       homepage,
                       identifier_uris,
                       available_to_other_tenants=False,
                       password=None,
                       reply_urls=None,
                       key_value=None,
                       key_type=None,
                       key_usage=None,
                       start_date=None,
                       end_date=None):
    password_creds, key_creds = _build_application_creds(
        password, key_value, key_type, key_usage, start_date, end_date)

    app_create_param = ApplicationCreateParameters(
        available_to_other_tenants,
        display_name,
        identifier_uris,
        homepage=homepage,
        reply_urls=reply_urls,
        key_credentials=key_creds,
        password_credentials=password_creds)

    try:
        return client.create(app_create_param)
    except GraphErrorException as ex:
        if 'insufficient privileges' in str(ex).lower():
            link = 'https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal'  # pylint: disable=line-too-long
            raise CLIError(
                "Directory permission is needed for the current user to register the application. "
                "For how to configure, please refer '{}'. Original error: {}".
                format(link, ex))
        raise
Esempio n. 6
0
def create_service_principal(name=None, secret=None, years=1):
    '''create a service principal you can use with login command

    :param str name: an unique uri. If missing, the command will generate one.
    :param str secret: the secret used to login. If missing, command will generate one.
    :param str years: Years the secret will be valid.
    '''
    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

    key_id = str(uuid.uuid4())
    end_date = start_date + relativedelta(years=years)
    secret = secret or str(uuid.uuid4())
    app_cred = PasswordCredential(start_date, end_date, key_id, secret)
    app_create_param = ApplicationCreateParameters(
        False,
        app_display_name,
        'http://' + app_display_name, [name],
        password_credentials=[app_cred])

    profile = Profile()
    cred, _, tenant = profile.get_login_credentials(for_graph_client=True)

    client = GraphRbacManagementClient(cred, tenant)

    #pylint: disable=no-member
    aad_application = client.applications.create(app_create_param)
    aad_sp = client.service_principals.create(aad_application.app_id, True)

    _build_output_content(name, aad_sp.object_id, secret, tenant)
Esempio n. 7
0
def create_application_registration(onefuzz_instance_name: str, name: str,
                                    approle: OnefuzzAppRole) -> Application:
    """ Create an application registration """

    client = get_client_from_cli_profile(GraphRbacManagementClient)
    apps: List[Application] = list(
        client.applications.list(filter="displayName eq '%s'" %
                                 onefuzz_instance_name))

    app = apps[0]
    resource_access = [
        ResourceAccess(id=role.id, type="Role") for role in app.app_roles
        if role.value == approle.value
    ]

    params = ApplicationCreateParameters(
        is_device_only_auth_supported=True,
        display_name=name,
        identifier_uris=[],
        password_credentials=[],
        required_resource_access=([
            RequiredResourceAccess(
                resource_access=resource_access,
                resource_app_id=app.app_id,
            )
        ] if len(resource_access) > 0 else []),
    )

    registered_app: Application = client.applications.create(params)

    atttempts = 5
    while True:
        if atttempts < 0:
            raise Exception(
                "Unable to create application registration, Please try again")

        atttempts = atttempts - 1
        try:
            time.sleep(5)
            query_microsoft_graph(
                method="PATCH",
                resource="applications/%s" % registered_app.object_id,
                body={
                    "publicClient": {
                        "redirectUris": [
                            "https://%s.azurewebsites.net" %
                            onefuzz_instance_name
                        ]
                    },
                    "isFallbackPublicClient": True,
                },
            )
            break
        except GraphQueryError as err:
            if err.status_code == 404:
                continue

    authorize_application(UUID(registered_app.app_id), UUID(app.app_id))
    return registered_app
Esempio n. 8
0
def create_application_registration(
    onefuzz_instance_name: str, name: str, approle: OnefuzzAppRole
) -> Application:
    """ Create an application registration """

    client = get_graph_client()
    apps: List[Application] = list(
        client.applications.list(filter="displayName eq '%s'" % onefuzz_instance_name)
    )

    app = apps[0]
    resource_access = [
        ResourceAccess(id=role.id, type="Role")
        for role in app.app_roles
        if role.value == approle.value
    ]

    params = ApplicationCreateParameters(
        is_device_only_auth_supported=True,
        display_name=name,
        identifier_uris=[],
        password_credentials=[],
        required_resource_access=(
            [
                RequiredResourceAccess(
                    resource_access=resource_access,
                    resource_app_id=app.app_id,
                )
            ]
            if len(resource_access) > 0
            else []
        ),
    )

    registered_app: Application = client.applications.create(params)

    atttempts = 5
    while True:
        if atttempts < 0:
            raise Exception(
                "Unable to create application registration, Please try again"
            )

        atttempts = atttempts - 1
        try:
            time.sleep(5)

            client = get_graph_client()
            update_param = ApplicationUpdateParameters(
                reply_urls=["https://%s.azurewebsites.net" % onefuzz_instance_name]
            )
            client.applications.patch(registered_app.object_id, update_param)

            break
        except Exception:
            continue

    authorize_application(UUID(registered_app.app_id), UUID(app.app_id))
    return registered_app
def create_application_registration(
    onefuzz_instance_name: str, name: str
) -> Application:
    """ Create an application registration """

    client = get_client_from_cli_profile(GraphRbacManagementClient)
    apps: List[Application] = list(
        client.applications.list(filter="displayName eq '%s'" % onefuzz_instance_name)
    )

    app = apps[0]
    resource_access = [
        ResourceAccess(id=role.id, type="Role") for role in app.app_roles
    ]

    params = ApplicationCreateParameters(
        is_device_only_auth_supported=True,
        display_name=name,
        identifier_uris=[],
        password_credentials=[],
        required_resource_access=(
            [
                RequiredResourceAccess(
                    resource_access=resource_access,
                    resource_app_id=app.app_id,
                )
            ]
            if len(resource_access) > 0
            else []
        ),
    )

    registered_app: Application = client.applications.create(params)
    body = {
        "publicClient": {
            "redirectUris": ["https://%s.azurewebsites.net" % onefuzz_instance_name]
        },
        "isFallbackPublicClient": True,
    }
    az_cli(
        [
            "rest",
            "-m",
            "PATCH",
            "-u",
            "https://graph.microsoft.com/v1.0/applications/%s"
            % registered_app.object_id,
            "--headers",
            "Content-Type=application/json",
            "-b",
            json.dumps(body),
        ]
    )
    authorize_application(UUID(registered_app.app_id), UUID(app.app_id))
    return registered_app
Esempio n. 10
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)
Esempio n. 11
0
    def createApp(self, key, appName):
        passwordCredential = PasswordCredential(start_date=datetime.datetime.now(),
                                                end_date="2299-12-31T06:08:04.0863895Z",
                                                value=key
                                                )

        resourceAccess = self.__getResourceAccessJson();

        if len(resourceAccess) == 0:
            raise Exception("No resource accesses found")
        parameters = ApplicationCreateParameters(available_to_other_tenants=False,
                                                 display_name=appName,
                                                 homepage=self.__identifierUrl,
                                                 identifier_uris=[self.__identifierUrl],
                                                 required_resource_access=resourceAccess,
                                                 password_credentials=[passwordCredential])
        application = self.getGraphRbacClient().applications.create(parameters)

        logging.info("Created App with id: " + application.app_id)
        return application.app_id
Esempio n. 12
0
def create_application(
    client,
    display_name,
    homepage,
    identifier_uris,
    available_to_other_tenants=False,
    password=None,
    reply_urls=None,
    key_value=None,
    key_type=None,
    key_usage=None,
    start_date=None,
    end_date=None,
    required_resource_accesses=None,
):
    password_creds, key_creds = _build_application_creds(
        password, key_value, key_type, key_usage, start_date, end_date)

    app_create_param = ApplicationCreateParameters(
        available_to_other_tenants=available_to_other_tenants,
        display_name=display_name,
        identifier_uris=identifier_uris,
        homepage=homepage,
        reply_urls=reply_urls,
        key_credentials=key_creds,
        password_credentials=password_creds,
        required_resource_access=required_resource_accesses,
    )
    try:
        result = client.create(app_create_param, raw=True)
        return result.output, result.response.headers["ocp-aad-session-key"]
    except GraphErrorException as ex:
        if "insufficient privileges" in str(ex).lower():
            link = "https://docs.microsoft.com/azure/azure-resource-manager/resource-group-create-service-principal-portal"  # pylint: disable=line-too-long
            raise AzCLIError(
                "Directory permission is needed for the current user to register the application. "
                "For how to configure, please refer '{}'. Original error: {}".
                format(link, ex))
        raise
Esempio n. 13
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)
Esempio n. 14
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)