diff --git a/src/cli/onefuzz/api.py b/src/cli/onefuzz/api.py index acae6e6b8..1e92722ef 100644 --- a/src/cli/onefuzz/api.py +++ b/src/cli/onefuzz/api.py @@ -1572,10 +1572,14 @@ class Onefuzz: client_secret: Optional[str] = None, enable_feature: Optional[PreviewFeature] = None, tenant_domain: Optional[str] = None, + reset: Optional[bool] = None, ) -> BackendConfig: """Configure onefuzz CLI""" self.logger.debug("set config") + if reset: + self._backend.config = BackendConfig(authority="", client_id="") + if endpoint is not None: # The normal path for calling the API always uses the oauth2 workflow, # which the devicelogin can take upwards of 15 minutes to fail in diff --git a/src/deployment/deploy.py b/src/deployment/deploy.py index 877f1fe7f..8d3c41023 100644 --- a/src/deployment/deploy.py +++ b/src/deployment/deploy.py @@ -65,7 +65,7 @@ from data_migration import migrate from registration import ( OnefuzzAppRole, add_application_password, - assign_scaleset_role, + assign_app_role, authorize_application, register_application, set_app_audience, @@ -525,10 +525,11 @@ class Client: logger.info("Upgrading: skipping assignment of the managed identity role") return logger.info("assigning the user managed identity role") - assign_scaleset_role( + assign_app_role( self.application_name, self.results["deploy"]["scaleset-identity"]["value"], self.get_subscription_id(), + OnefuzzAppRole.ManagedNode, ) def apply_migrations(self) -> None: diff --git a/src/deployment/registration.py b/src/deployment/registration.py index a175f338f..ed0d70a87 100644 --- a/src/deployment/registration.py +++ b/src/deployment/registration.py @@ -26,6 +26,7 @@ from azure.graphrbac.models import ( RequiredResourceAccess, ResourceAccess, ServicePrincipal, + ServicePrincipalCreateParameters, ) from functional import seq from msrest.serialization import TZ_UTC @@ -200,6 +201,16 @@ def create_application_registration( registered_app: Application = 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=registered_app.app_id, + ) + + client.service_principals.create(service_principal_params) + atttempts = 5 while True: if atttempts < 0: @@ -221,6 +232,9 @@ def create_application_registration( continue authorize_application(UUID(registered_app.app_id), UUID(app.app_id)) + assign_app_role( + onefuzz_instance_name, name, subscription_id, OnefuzzAppRole.ManagedNode + ) return registered_app @@ -395,8 +409,11 @@ def update_pool_registration(onefuzz_instance_name: str, subscription_id: str) - ) -def assign_scaleset_role_manually( - onefuzz_instance_name: str, scaleset_name: str, subscription_id: str +def assign_app_role_manually( + onefuzz_instance_name: str, + application_name: str, + subscription_id: str, + app_role: OnefuzzAppRole, ) -> None: client = get_graph_client(subscription_id) @@ -419,7 +436,7 @@ def assign_scaleset_role_manually( onefuzz_service_principal = onefuzz_service_principals[0] scaleset_service_principals: List[ServicePrincipal] = list( - client.service_principals.list(filter="displayName eq '%s'" % scaleset_name) + client.service_principals.list(filter="displayName eq '%s'" % application_name) ) if not scaleset_service_principals: @@ -428,7 +445,7 @@ def assign_scaleset_role_manually( scaleset_service_principal.app_roles app_roles: List[AppRole] = [ - role for role in app.app_roles if role.value == OnefuzzAppRole.ManagedNode.value + role for role in app.app_roles if role.value == app_role.value ] if not app_roles: @@ -455,12 +472,15 @@ def assign_scaleset_role_manually( ) -def assign_scaleset_role( - onefuzz_instance_name: str, scaleset_name: str, subscription_id: str +def assign_app_role( + onefuzz_instance_name: str, + application_name: str, + subscription_id: str, + app_role: OnefuzzAppRole, ) -> None: """ - Allows the nodes in the scaleset to access the service by assigning - their managed identity to the ManagedNode Role + Allows the application to access the service by assigning + their managed identity to the provided App Role """ try: onefuzz_service_appId = query_microsoft_graph( @@ -471,11 +491,9 @@ def assign_scaleset_role( "$select": "appId", }, ) - if len(onefuzz_service_appId["value"]) == 0: raise Exception("onefuzz app registration not found") appId = onefuzz_service_appId["value"][0]["appId"] - onefuzz_service_principals = query_microsoft_graph( method="GET", resource="servicePrincipals", @@ -485,28 +503,25 @@ def assign_scaleset_role( if len(onefuzz_service_principals["value"]) == 0: raise Exception("onefuzz app service principal not found") onefuzz_service_principal = onefuzz_service_principals["value"][0] - scaleset_service_principals = query_microsoft_graph( method="GET", resource="servicePrincipals", - params={"$filter": "displayName eq '%s'" % scaleset_name}, + params={"$filter": "displayName eq '%s'" % application_name}, ) if len(scaleset_service_principals["value"]) == 0: raise Exception("scaleset service principal not found") scaleset_service_principal = scaleset_service_principals["value"][0] - managed_node_role = ( seq(onefuzz_service_principal["appRoles"]) - .filter(lambda x: x["value"] == OnefuzzAppRole.ManagedNode.value) + .filter(lambda x: x["value"] == app_role.value) .head_option() ) if not managed_node_role: raise Exception( - "ManagedNode role not found in the OneFuzz application " + f"{app_role.value} role not found in the OneFuzz application " "registration. Please redeploy the instance" ) - assignments = query_microsoft_graph( method="GET", resource="servicePrincipals/%s/appRoleAssignments" @@ -529,8 +544,8 @@ def assign_scaleset_role( }, ) except adal.AdalError: - assign_scaleset_role_manually( - onefuzz_instance_name, scaleset_name, subscription_id + assign_app_role_manually( + onefuzz_instance_name, application_name, subscription_id, app_role ) @@ -622,8 +637,11 @@ def main() -> None: args.subscription_id, ) elif args.command == "assign_scaleset_role": - assign_scaleset_role( - onefuzz_instance_name, args.scaleset_name, args.subscription_id + assign_app_role( + onefuzz_instance_name, + args.scaleset_name, + args.subscription_id, + OnefuzzAppRole.ManagedNode, ) else: raise Exception("invalid arguments")