def __init__(self, kms_key_arn, s3_bucket, role):
     self.iam = IAM(boto3)
     self.iam.update_iam_roles(s3_bucket, kms_key_arn,
                               IAMUpdater.role_policies)
     self.iam_target_account = IAM(role)
     self.iam_target_account.update_iam_target_account_roles(
         kms_key_arn, IAMUpdater.target_role_policies)
Ejemplo n.º 2
0
def get_iam_client():
    app_code = env.BKAPP_SOPS_IAM_APP_CODE
    app_secret = env.BKAPP_SOPS_IAM_APP_SECRET_KEY
    if settings.BK_IAM_SKIP:
        return DummyIAM(app_code, app_secret, settings.BK_IAM_INNER_HOST,
                        settings.BK_PAAS_ESB_HOST)
    if settings.BK_IAM_APIGW_HOST:
        return IAM(app_code,
                   app_secret,
                   bk_apigateway_url=settings.BK_IAM_APIGW_HOST)
    return IAM(app_code, app_secret, settings.BK_IAM_INNER_HOST,
               settings.BK_PAAS_ESB_HOST)
Ejemplo n.º 3
0
def update_iam(role, s3_buckets, kms_key_arns, role_policies):
    iam = IAM(role.client("iam"))
    iam.update_iam_roles(
        s3_buckets,
        kms_key_arns,
        role_policies
    )
Ejemplo n.º 4
0
class ApplyURLGenerator:
    iam = IAM(
        settings.APP_CODE,
        settings.SECRET_KEY,
        settings.BK_IAM_HOST,
        settings.BK_PAAS_INNER_HOST,
        settings.BK_IAM_APIGATEWAY_URL,
    )

    @classmethod
    def generate_apply_url(
            cls, username: str,
            action_request_list: List[ActionResourcesRequest]) -> str:
        """
        生成权限申请跳转 url
        参考 https://github.com/TencentBlueKing/iam-python-sdk/blob/master/docs/usage.md#14-获取无权限申请跳转url
        """
        app = cls._make_application(action_request_list)
        ok, message, url = cls.iam.get_apply_url(app, bk_username=username)
        if not ok:
            logger.error('generate_apply_url failed: %s', message)
            return settings.BK_IAM_APP_URL
        return url

    @staticmethod
    def _make_application(
        action_request_list: List[ActionResourcesRequest]
    ) -> models.Application:
        """为 generate_apply_url 方法生成 models.Application"""
        return models.Application(
            settings.BK_IAM_SYSTEM_ID,
            actions=[req.to_action() for req in action_request_list])
def update_iam(role, s3_bucket, kms_key_arn, role_policies):
    iam = IAM(role)
    iam.update_iam_roles(
        s3_bucket,
        kms_key_arn,
        role_policies
    )
Ejemplo n.º 6
0
    def authenticate_credentials(self, userid, password):
        if userid != "bk_iam":
            raise AuthenticationFailed("username is not bk_iam")

        iam = IAM(settings.APP_ID, settings.APP_TOKEN, settings.BK_IAM_HOST, settings.BK_PAAS_INNER_HOST)
        ok, msg, token = iam.get_token(settings.APP_ID)
        if not ok:
            raise AuthenticationFailed(f"get system token fail: {msg}")
        if password != token:
            raise AuthenticationFailed("password in basic_auth not equals to system token")

        return (FancyDict(username=userid, password=password), None)
Ejemplo n.º 7
0
    def authenticate_credentials(self,
                                 userid: str,
                                 password: str,
                                 request=None):
        if userid != "bk_iam":
            raise AuthenticationFailed("username is not bk_iam")

        iam = IAM(
            settings.APP_CODE,
            settings.SECRET_KEY,
            settings.BK_IAM_HOST,
            settings.BK_PAAS_INNER_HOST,
            settings.BK_IAM_APIGATEWAY_URL,
        )
        ok, msg, token = iam.get_token(settings.BK_IAM_SYSTEM_ID)
        if not ok:
            raise AuthenticationFailed(f"get system token fail: {msg}")
        if password != token:
            raise AuthenticationFailed(
                "password in basic_auth not equals to system token")

        return (FancyDict(username=userid, password=password), None)
Ejemplo n.º 8
0
class ProjectFilter:
    """
    项目权限过滤器.
    note: 用于查询用户具有 project_view 权限的所有项目(iam v3 本身不支持这种查询)
    """

    iam = IAM(
        settings.APP_CODE,
        settings.SECRET_KEY,
        settings.BK_IAM_HOST,
        settings.BK_PAAS_INNER_HOST,
        settings.BK_IAM_APIGATEWAY_URL,
    )

    def make_view_perm_filter(self, username: str) -> Dict:
        request = Request(
            settings.BK_IAM_SYSTEM_ID,
            Subject('user', username),
            Action(ProjectAction.VIEW),
            None,
            None,
        )
        policies = self._do_policy_query(request)
        if not policies:
            return {}

        return self._make_dict_filter(policies)

    @staticmethod
    def op_is_any(dict_filter: Dict[str, List[str]]) -> bool:
        if not dict_filter:
            return False
        if dict_filter.get('op') == OP.ANY:
            return True
        return False

    def _do_policy_query(self, request) -> Optional[Dict]:
        # 1. validate
        if not isinstance(request, Request):
            raise AuthInvalidRequest(
                'request should be instance of iam.auth.models.Request')

        request.validate()

        # 2. _client.policy_query
        policies = self.iam._do_policy_query(request)

        # the polices maybe none
        if not policies:
            return None

        return policies

    @staticmethod
    def _make_dict_filter(policies: Dict) -> Dict:
        """
        基于策略规则, 生成 project_id 过滤器

        :param policies: 权限中心返回的策略规则, 如 {'op': OP.IN, 'value': [2, 1], 'field': 'project.id'}
        :return: project_id 过滤器, 如 {'value': [1, 2], 'op': OP.IN}
        """
        op = policies['op']
        if op not in [OP.IN, OP.EQ, OP.ANY, OP.OR, OP.AND]:
            raise AuthInvalidRequest(
                f'make_dict_filter does not support op:{op}')

        if op == OP.EQ:
            return {'value': [policies['value']], 'op': OP.IN}

        if op in [OP.IN, OP.ANY]:
            return {'value': policies['value'] or [], 'op': op}

        # 如果 op 是 OP.OR 或 OP.AND,只处理一级,不考虑嵌套的情况
        value_list = []
        for policy in policies['content']:
            if policy['field'] != 'project.id':
                continue

            op = policy['op']
            if op == OP.ANY:
                return {'value': policy['value'] or [], 'op': op}

            value = policy['value']
            if op == OP.IN:
                value_list.extend(value)
            elif op == OP.EQ:
                value_list.append(value)

        return {'value': list(set(value_list)), 'op': OP.IN}
Ejemplo n.º 9
0
class IAMClient:
    """提供基础的 iam client 方法封装"""

    iam = IAM(settings.APP_ID, settings.APP_TOKEN, settings.BK_IAM_HOST,
              settings.BK_PAAS_INNER_HOST)

    def resource_type_allowed(self,
                              username: str,
                              action_id: str,
                              use_cache: bool = False) -> bool:
        """
        判断用户是否具备某个操作的权限
        note: 权限判断与资源实例无关,如创建某资源
        """
        request = self._make_request(username, action_id)
        if not use_cache:
            return self.iam.is_allowed(request)
        return self.iam.is_allowed_with_cache(request)

    def resource_inst_allowed(self,
                              username: str,
                              action_id: str,
                              res_request: ResourceRequest,
                              use_cache: bool = False) -> bool:
        """
        判断用户对某个资源实例是否具有指定操作的权限
        note: 权限判断与资源实例有关,如更新某个具体资源
        """
        request = self._make_request(username,
                                     action_id,
                                     resources=res_request.make_resources())
        if not use_cache:
            return self.iam.is_allowed(request)
        return self.iam.is_allowed_with_cache(request)

    def resource_type_multi_actions_allowed(
            self, username: str, action_ids: List[str]) -> Dict[str, bool]:
        """
        判断用户是否具备多个操作的权限
        note: 权限判断与资源实例无关,如创建某资源

        :returns 示例 {'project_create': True}
        """
        return {
            action_id: self.resource_type_allowed(username, action_id)
            for action_id in action_ids
        }

    def resource_inst_multi_actions_allowed(
            self, username: str, action_ids: List[str],
            res_request: ResourceRequest) -> Dict[str, bool]:
        """
        判断用户对某个资源实例是否具有多个操作的权限.
        note: 权限判断与资源实例有关,如更新某个具体资源

        :return 示例 {'project_view': True, 'project_edit': False}
        """
        actions = [Action(action_id) for action_id in action_ids]
        request = MultiActionRequest(settings.APP_ID,
                                     Subject("user", username), actions,
                                     res_request.make_resources(), None)
        return self.iam.resource_multi_actions_allowed(request)

    def batch_resource_multi_actions_allowed(
            self, username: str, action_ids: List[str],
            res_request: ResourceRequest) -> Dict[str, Dict[str, bool]]:
        """
        判断用户对某些资源是否具有多个指定操作的权限
        note: 当前sdk仅支持同类型的资源

        :return 示例 {'0ad86c25363f4ef8adcb7ac67a483837': {'project_view': True, 'project_edit': False}}
        """
        actions = [Action(action_id) for action_id in action_ids]
        request = MultiActionRequest(settings.APP_ID,
                                     Subject("user",
                                             username), actions, [], None)
        resources_list = [[res] for res in res_request.make_resources()]
        return self.iam.batch_resource_multi_actions_allowed(
            request, resources_list)

    def _make_request(self,
                      username: str,
                      action_id: str,
                      resources: Optional[List[Resource]] = None) -> Request:
        return Request(
            settings.APP_ID,
            Subject("user", username),
            Action(action_id),
            resources,
            None,
        )

    def _grant_resource_creator_actions(self, username: str, data: Dict):
        """
        用于创建资源时,注册用户对该资源的关联操作权限.
        note: 具体的关联操作见权限模型的 resource_creator_actions 字段
        """
        return self.iam._client.grant_resource_creator_actions(
            None, username, data)
Ejemplo n.º 10
0
class IAMClient:
    """提供基础的 iam client 方法封装"""

    iam = IAM(
        settings.APP_CODE,
        settings.SECRET_KEY,
        settings.BK_IAM_HOST,
        settings.BK_PAAS_INNER_HOST,
        settings.BK_IAM_APIGATEWAY_URL,
    )

    def resource_type_allowed(self, username: str, action_id: str, use_cache: bool = False) -> bool:
        """
        判断用户是否具备某个操作的权限
        note: 权限判断与资源实例无关,如创建某资源
        """
        request = self._make_request(username, action_id)
        if not use_cache:
            return self.iam.is_allowed(request)
        return self.iam.is_allowed_with_cache(request)

    def resource_inst_allowed(
        self, username: str, action_id: str, resources: List[Resource], use_cache: bool = False
    ) -> bool:
        """
        判断用户对某个资源实例是否具有指定操作的权限
        note: 权限判断与资源实例有关,如更新某个具体资源
        """
        request = self._make_request(username, action_id, resources=resources)
        if not use_cache:
            return self.iam.is_allowed(request)
        return self.iam.is_allowed_with_cache(request)

    def resource_type_multi_actions_allowed(self, username: str, action_ids: List[str]) -> Dict[str, bool]:
        """
        判断用户是否具备多个操作的权限
        note: 权限判断与资源实例无关,如创建某资源

        :returns 示例 {'project_create': True}
        """
        return {action_id: self.resource_type_allowed(username, action_id) for action_id in action_ids}

    def resource_inst_multi_actions_allowed(
        self, username: str, action_ids: List[str], resources: List[Resource]
    ) -> Dict[str, bool]:
        """
        判断用户对某个(单个)资源实例是否具有多个操作的权限.
        note: 权限判断与资源实例有关,如更新某个具体资源

        :return 示例 {'project_view': True, 'project_edit': False}
        """
        actions = [Action(action_id) for action_id in action_ids]
        request = MultiActionRequest(settings.BK_IAM_SYSTEM_ID, Subject("user", username), actions, resources, None)
        return self.iam.resource_multi_actions_allowed(request)

    def batch_resource_multi_actions_allowed(
        self, username: str, action_ids: List[str], resources: List[Resource]
    ) -> Dict[str, Dict[str, bool]]:
        """
        判断用户对某些资源是否具有多个指定操作的权限. 当前sdk仅支持同类型的资源
        :return 示例 {'0ad86c25363f4ef8adcb7ac67a483837': {'project_view': True, 'project_edit': False}}
        """
        actions = [Action(action_id) for action_id in action_ids]
        request = MultiActionRequest(settings.BK_IAM_SYSTEM_ID, Subject("user", username), actions, [], None)
        resources_list = [[res] for res in resources]
        return self.iam.batch_resource_multi_actions_allowed(request, resources_list)

    def _make_request(self, username: str, action_id: str, resources: Optional[List[Resource]] = None) -> Request:
        return Request(
            settings.BK_IAM_SYSTEM_ID,
            Subject("user", username),
            Action(action_id),
            resources,
            None,
        )
Ejemplo n.º 11
0
    def __init__(self,
                 app_name,
                 image,
                 user_data_file,
                 task_definition=None,
                 service=None,
                 desired_count=1,
                 max_health=None,
                 min_health=None,
                 container_definitions=None,
                 key_name=None,
                 security_groups=None,
                 user_data=None,
                 lambda_role=None,
                 aws_parameters=None):
        '''

		:type user_data_file: string
		:param user_data_file: path a .txt file containing bash
			commands to be executed on an EC2 instance at launch
			time. At least, the commands must set the following 
			parameters: 

			`ECS_CLUSTER` 

			and

			{"auths": 
				{
					`dkr.ecr.region.awsamazon.com`: { "auth": `auth_tocken` }
					"https://index.docker.io/v1/": { "auth": `auth_token` }
				}

			must be set in the following file: /etc/ecs/ecs.config in the 
			EC2 instance. See the AWS documentation for further information:
			##############################URL. 

		:type max_health: int
		:param max_health: maximumPercent for the deployment 
			configuration of an ECS service. Default value in 
			the AWS API is 200.

		:type min_health: int
		:param min_health: minimumHealthyPercent for the deployment 
			configuration of an ECS service. Default value in the 
			AWS API is 50. 

		:type key_name: string
		:param key_name: name of the ssh key pair to be used when 
			creating EC2 instances within the cluster.b 
		'''
        self.app_name = app_name

        # The following parameters are automatically assigned
        # based on the name of the application following a
        # default naming structure. This is to ensure that we
        # follow a systematic and ordered approachto naming our
        # resources that makes it easier to identify and locate
        # them.
        # Users are free to modify these attributes by repointing
        # them to different strings. This might be warranted in
        # cases in which some flexibility is required. For this
        # reason, the attributes are not readonly.
        # Users who modify these attributes are responsible for
        # keeping track of the resources they create associated
        # with the cluster.
        self.cluster_name = app_name + '_cluster'
        self.service_name = app_name + '_service'
        self.task_name = app_name + '_task'
        if container_definitions is None:
            self.container_definitions = []
        else:
            self.container_definitions = container_definitions
        self.task_definition = task_definition
        self.service = service

        self.image = image
        self.desired_count = desired_count
        self.min_health = min_health
        self.max_health = max_health

        self.key_name = key_name
        self.user_data_file = user_data_file
        self.user_data = user_data
        self.security_groups = security_groups
        self._instances = []

        self.lambda_role = lambda_role
        #self.default_lambda_role = 'lambda_ecs_role'

        self.aws_parameters = aws_parameters
        self._make_clients()

        ## Allow passing aws connection parameters to get
        ## the connections.
        self.ec2 = EC2Instance(None, None, None)
        self.iam = IAM()
        self.sns = SNS()
        self.awslambda = Lambda()

        self._cluster = None
Ejemplo n.º 12
0
def cls():
    cls = IAM(boto3)
    cls.client = Mock()
    cls.client.get_role_policy.return_value = stub_iam.get_role_policy
    cls._fetch_policy_document('some_role_name', 'some_policy_name')
    return cls
Ejemplo n.º 13
0
if __name__ == "__main__":
    # eval
    print("\nTHE EVAL EXAMPLE:\n")
    eval_exmaple()

    print_spearator()

    # convert to sql / django queryset
    print("\nTHE CONVERT EXAMPLE:\n")
    convert_example()

    # make a request
    print_spearator()

    subject = Subject("user", "admin")
    # action = Action("edit_app")
    # action = Action("access_developer_center")
    action = Action("develop_app")
    resource = Resource("bk_paas", "app", "bk_test", {})

    request = Request("bk_paas", subject, action, [resource], None)

    print("the request: ", request.to_dict())

    iam = IAM("bk_paas", "2353e89a-10a2-4f30-9f6b-8973e9cd1404",
              "http://127.0.0.1:8080", "https://{PAAS_DOMAIN}")
    # recommend if got an APIGateway
    # iam = IAM("bk_paas", "2353e89a-10a2-4f30-9f6b-8973e9cd1404", bk_apigateway_url="http://{IAM_APIGATEWAY_URL}")
    print("is_allowed: ", iam.is_allowed(request))
    print("query: ", iam.make_filter(request))
Ejemplo n.º 14
0
def insert_mockdata():
    src = Path(get_source_dir()) / 'data' / 'mock_data.yaml'
    if not src.exists():
        raise FileNotFoundError(
            'You need a mock_data.yaml placed under the data/ folder.')
    with open(src) as f:
        data = yaml.load(f)
    # Log into IAM as ERP
    envyaml_path = Path(get_source_dir()) / 'data/envs/env.yaml'
    with open(envyaml_path) as f:
        envs = yaml.load(f)
    appid = envs['appids']['erp']
    iam = IAM("http://localhost:15002", appid, None,
              str(Path(get_source_dir()) / 'data/keys/erp.pem'))
    backplane = Backplane('http://localhost:15003')
    for user in data.get('users', {}).values():
        try:
            user_id = iam.user_register(user['name'], user['email'],
                                        user['password'])['result']
            user['user_id'] = user_id
            # Now it's a user. We'll start promoting it to other roles.
            if user.get('role') in ['dev', 'member', 'admin']:
                iam.set_user_profile(user_id, role='dev')
            if user.get('role') in ['member', 'admin']:
                iam.set_user_profile(user_id, role='member')
            if user.get('role') in ['admin']:
                iam.set_user_profile(user_id, role='admin')
        except HTTPError as e:
            if e.response.status_code == 403:
                print('\n-!> Skipping user [%s]: exists' % user['name'])

    for lcodename, lifecycle in data.get('devcats').items():
        # First we check if that is actually there
        lcfound = False
        try:
            lcfound = bool(DeviceLifecycle(backplane).get(lcodename))
        except:
            pass
        if lcfound:
            print('\n-!> Skipping lifecycle [%s]: exists' % lcodename)
            continue
        try:
            lifecycle['codename'] = lcodename
            lifecycle['status'] = 'SUPPORTED'
            l = DeviceLifecycle(backplane, True, **lifecycle)
            l.save()
        except Exception as e:
            print('\n-!> Failed to create lifecycle [%s]: %s' % (lcodename, e))

    for appcat_id, appcat in data.get('appcats').items():
        # First we check if that is actually there
        found = False
        try:
            found = bool(AppCat(backplane).get(appcat_id))
        except:
            pass
        if found:
            print('\n-!> Skipping appcat [%s]: exists' % appcat_id)
            continue
        try:
            appcat['_id'] = appcat_id
            a = AppCat(backplane, True, **appcat)
            a.save()
        except Exception as e:
            print('\n-!> Failed to create appcat [%s]: %s' % (lcodename, e))
            raise

    sites = {s.name: s._id for s in Site(backplane).list()}
    for site_name, site in data.get('sites', {}).items():
        # First we check if the site is actually there
        if site_name in sites:
            print('\n-!> Skipping site [%s]: exists' % site_name)
            site['site_id'] = sites[site_name]
            continue
        try:
            # Substitude the owner id
            owner = site.pop('owner', None)
            if owner:
                site['owner_id'] = data.get('users', {}).get(owner,
                                                             {}).get('user_id')
            site['name'] = site_name
            s = Site(backplane, True, **site)
            s.save()
            site['site_id'] = s._id
        except Exception as e:
            print('\n-!> Failed to create site [%s]: %s' % (site_name, e))

    for device_id, node in data.get('nodes', {}).items():
        # First we check if the node is actually there
        if Node(backplane).list(device_id=device_id):
            print('\n-!> Skipping node [%s]: exists' % hex(device_id))
            continue
        try:
            node['owner_id'] = None
            node['site_id'] = None
            # Substitude the owner id
            owner = node.pop('owner', None)
            if owner:
                node['owner_id'] = data.get('users', {}).get(owner,
                                                             {}).get('user_id')
            # Substitude the site id
            site = node.pop('site', None)
            if site:
                node['site_id'] = data.get('sites', {}).get(site,
                                                            {}).get('site_id')
            node['device_id'] = device_id
            n = Node(backplane, True, **node)
            n.save()
            node['node_id'] = n._id
        except Exception as e:
            print('\n-!> Failed to create node [%s]: %s' % (hex(device_id), e))

    for device_id, router in data.get('routers', {}).items():
        # First we check if the router is actually there
        if Router(backplane).list(device_id=device_id):
            print('\n-!> Skipping router [%s]: exists' % hex(device_id))
            continue
        try:
            router['owner_id'] = None
            # Substitude the owner id
            owner = router.pop('owner', None)
            if owner:
                router['owner_id'] = data.get('users',
                                              {}).get(owner, {}).get('user_id')
            router['device_id'] = device_id
            n = Router(backplane, True, **router)
            n.save()
            router['router_id'] = n._id
        except Exception as e:
            print('\n-!> Failed to create router [%s]: %s' %
                  (hex(device_id), e))
    dest = Path(get_source_dir()) / 'data' / 'mock_data.results.yaml'
    with open(dest, 'w') as fp:
        yaml.dump(data, fp)
Ejemplo n.º 15
0
from logger import Logger
from iam import IAM
from cloudformation import Cloudformation

logger = Logger(loglevel='info')
iam = IAM(logger, region='us-west-2')
cf = Cloudformation(logger, region='us-west-2')

RoleName=''

cfoutput = cf.describe_stack('')
for keys in cfoutput['Stacks'][0]['Outputs']:
    if keys['OutputKey'] == 'InstanceRoleARN':
        iam_role_arn = keys['OutputValue']

role = ""
role_name = role.split("/")[-1]
logger.info(role_name)

role_info = iam.list_role_policies(RoleName=RoleName)
if 'ASG-Policy-For-Worker' in role_info:
    logger.info('found role')
    iam.delete_role_policy(
        RoleName=RoleName
    )