1111from urllib .parse import urlparse
1212
1313from azure .cli .core .commands .arm import ArmTemplateBuilder
14+ from azure .cli .core .commands .client_factory import get_mgmt_service_client
15+ from azure .cli .core .profiles import ResourceType , get_sdk
1416
1517from knack .log import get_logger
1618from knack .util import CLIError
@@ -757,3 +759,76 @@ def _open(filename, mode):
757759 f .write (public_bytes )
758760
759761 return public_bytes .decode ()
762+
763+
764+ def _gen_guid ():
765+ import uuid
766+ return uuid .uuid4 ()
767+
768+
769+ def assign_identity (cli_ctx , getter , setter , identity_role = None , identity_scope = None ):
770+ import time
771+ from azure .core .exceptions import HttpResponseError
772+
773+ # get
774+ resource = getter ()
775+ resource = setter (resource )
776+
777+ # create role assignment:
778+ if identity_scope :
779+ principal_id = resource .get ('identity' ).get ('principal_id' )
780+
781+ identity_role_id = resolve_role_id (cli_ctx , identity_role , identity_scope )
782+ assignments_client = get_mgmt_service_client (cli_ctx , ResourceType .MGMT_AUTHORIZATION ).role_assignments
783+ RoleAssignmentCreateParameters = get_sdk (cli_ctx , ResourceType .MGMT_AUTHORIZATION ,
784+ 'RoleAssignmentCreateParameters' , mod = 'models' ,
785+ operation_group = 'role_assignments' )
786+ parameters = RoleAssignmentCreateParameters (role_definition_id = identity_role_id , principal_id = principal_id ,
787+ principal_type = None )
788+
789+ logger .info ("Creating an assignment with a role '%s' on the scope of '%s'" , identity_role_id , identity_scope )
790+ retry_times = 36
791+ assignment_name = _gen_guid ()
792+ for retry_time in range (0 , retry_times ):
793+ try :
794+ assignments_client .create (scope = identity_scope , role_assignment_name = assignment_name ,
795+ parameters = parameters )
796+ break
797+ except HttpResponseError as ex :
798+ if ex .error .code == 'RoleAssignmentExists' :
799+ logger .info ('Role assignment already exists' )
800+ break
801+ if retry_time < retry_times and ' does not exist in the directory ' in ex .message :
802+ time .sleep (5 )
803+ logger .warning ('Retrying role assignment creation: %s/%s' , retry_time + 1 ,
804+ retry_times )
805+ continue
806+ raise
807+ return resource
808+
809+
810+ def resolve_role_id (cli_ctx , role , scope ):
811+ import uuid
812+ client = get_mgmt_service_client (cli_ctx , ResourceType .MGMT_AUTHORIZATION ).role_definitions
813+
814+ role_id = None
815+ if re .match (r'/subscriptions/[^/]+/providers/Microsoft.Authorization/roleDefinitions/' ,
816+ role , re .I ):
817+ role_id = role
818+ else :
819+ try :
820+ uuid .UUID (role )
821+ role_id = '/subscriptions/{}/providers/Microsoft.Authorization/roleDefinitions/{}' .format (
822+ client .config .subscription_id , role )
823+ except ValueError :
824+ pass
825+ if not role_id : # retrieve role id
826+ role_defs = list (client .list (scope , "roleName eq '{}'" .format (role )))
827+ if not role_defs :
828+ raise CLIError ("Role '{}' doesn't exist." .format (role ))
829+ if len (role_defs ) > 1 :
830+ ids = [r .id for r in role_defs ]
831+ err = "More than one role matches the given name '{}'. Please pick an id from '{}'"
832+ raise CLIError (err .format (role , ids ))
833+ role_id = role_defs [0 ].id
834+ return role_id
0 commit comments