|
34 | 34 | from .policy.pm_cloud import (build_policy_spec, validate_policy_spec, AccountDetails, build_cit_request, build_user, |
35 | 35 | UserDetails, build_company, build_apikey, build_app_update_request, get_ca_info, |
36 | 36 | CertificateAuthorityDetails, CertificateAuthorityInfo, build_account_details, |
37 | | - build_app_create_request, supported_rsa_key_sizes, supported_elliptic_curves) |
38 | | -from .vaas_utils import AppDetails, RecommendedSettings, EdgeEncryptionKey, zip_to_pem, value_matches_regex |
| 37 | + build_app_create_request, build_team, get_cit_data_from_response, build_owner_json, |
| 38 | + supported_rsa_key_sizes, supported_elliptic_curves) |
| 39 | +from .vaas_utils import AppDetails, OwnerIdsAndTypes, RecommendedSettings, EdgeEncryptionKey, zip_to_pem, value_matches_regex |
39 | 40 |
|
40 | 41 | TOKEN_HEADER_NAME = "tppl-api-key" # nosec |
41 | 42 | APPLICATION_SERVER_TYPE_ID = "784938d1-ef0d-11eb-9461-7bb533ba575b" |
|
57 | 58 | CSR_ATTR_KEY_TYPE = 'keyType' |
58 | 59 | CSR_ATTR_KEY_LENGTH = 'keyLength' |
59 | 60 | CSR_ATTR_KEY_CURVE = 'keyCurve' |
| 61 | +OWNER_TYPE_USER = "USER" |
| 62 | +OWNER_TYPE_TEAM = "TEAM" |
60 | 63 |
|
61 | 64 | log = get_child("connection-vaas") |
62 | 65 |
|
@@ -94,6 +97,9 @@ def __init__(self): |
94 | 97 | ISSUING_TEMPLATES_UPDATE = ISSUING_TEMPLATES + "/{}" |
95 | 98 | USER_ACCOUNTS = API_VERSION + "useraccounts" |
96 | 99 | DEK_PUBLIC_KEY = API_VERSION + "edgeencryptionkeys/{}" |
| 100 | + USERS_USERNAME = API_VERSION + "users/username/{}" |
| 101 | + USERS_ID = API_VERSION + "users/{}" |
| 102 | + TEAMS_ID = API_VERSION + "teams" |
97 | 103 |
|
98 | 104 |
|
99 | 105 | class CondorChainOptions: |
@@ -126,6 +132,16 @@ def _parse_zone(zone): |
126 | 132 | return app_name, cit_alias |
127 | 133 |
|
128 | 134 |
|
| 135 | +def create_owner(owner_type, owner_id): |
| 136 | + owner = OwnerIdsAndTypes(owner_type, owner_id) |
| 137 | + return owner |
| 138 | + |
| 139 | + |
| 140 | +def resolve_apikey_owner(user_details): |
| 141 | + owner = create_owner(OWNER_TYPE_USER, user_details.user.user_id) |
| 142 | + return owner |
| 143 | + |
| 144 | + |
129 | 145 | class CloudConnection(CommonConnection): |
130 | 146 | def __init__(self, token, url=None, http_request_kwargs=None): |
131 | 147 | super().__init__() |
@@ -628,22 +644,118 @@ def set_policy(self, zone, policy_spec): |
628 | 644 | raise VenafiError('User Details not found') |
629 | 645 |
|
630 | 646 | app_details = self._get_app_details_by_name(app_name) |
| 647 | + for_update, owners_list = self.resolve_owners(policy_spec.users, user_details) |
631 | 648 | if app_details: |
632 | | - # Application exists. Update with cit |
633 | | - if not self._policy_exists(zone): |
| 649 | + # Application exists. Update with cit and owners |
| 650 | + if for_update and len(policy_spec.users) == 0: |
| 651 | + log.debug("No users provided in the policy specification") |
| 652 | + else: |
| 653 | + owner_list = build_owner_json(owners_list) |
| 654 | + app_details.owner_ids_and_types = owner_list |
| 655 | + if app_details.cit_alias_id_map: |
634 | 656 | # Only link cit with Application when cit is not already associated with Application |
635 | | - app_req = build_app_update_request(app_details, resp_cit_data) |
636 | | - status, data = self._put(URLS.APP_BY_ID.format(app_details.app_id), app_req) |
637 | | - if status != HTTPStatus.OK: |
638 | | - raise VenafiError(f"Could not update Application [{app_name}] with cit [{resp_cit_data}]") |
| 657 | + cit_map = app_details.cit_alias_id_map |
| 658 | + cit_id, cit_name = get_cit_data_from_response(cit_data) |
| 659 | + cit_map[cit_name] = cit_id |
| 660 | + app_req = build_app_update_request(app_details, cit_map) |
| 661 | + status, data = self._put(URLS.APP_BY_ID.format(app_details.app_id), app_req) |
| 662 | + if status != HTTPStatus.OK: |
| 663 | + raise VenafiError(f"Could not update Application [{app_name}] with cit [{resp_cit_data}]") |
639 | 664 | else: |
640 | 665 | # Application does not exist. Create one |
641 | | - app_req = build_app_create_request(app_name, user_details, resp_cit_data) |
| 666 | + app_req = build_app_create_request(app_name, owners_list, resp_cit_data) |
642 | 667 | status, data = self._post(URLS.APPLICATIONS, app_req) |
643 | 668 | if status != HTTPStatus.CREATED: |
644 | 669 | raise VenafiError(f"Could not create application [{app_name}]") |
645 | 670 | return |
646 | 671 |
|
| 672 | + def resolve_owners(self, users_list, user_details): |
| 673 | + owners_list = list() |
| 674 | + for_update = False |
| 675 | + if not users_list: |
| 676 | + # When no users are provided on the list, adds apikey user as owner |
| 677 | + api_owner = resolve_apikey_owner(user_details) |
| 678 | + owners_list.append(api_owner) |
| 679 | + for_update = True |
| 680 | + else: |
| 681 | + # Resolving the usernames list |
| 682 | + # Creating a higher level Teams object to cache the response |
| 683 | + teams_list = list() |
| 684 | + users_list = list(set(users_list)) |
| 685 | + for username in users_list: |
| 686 | + cloud_owner = self.resolve_user_to_cloud_owner(username) |
| 687 | + if cloud_owner: |
| 688 | + owners_list.append(cloud_owner) |
| 689 | + else: |
| 690 | + team_owner = self.resolve_user_to_cloud_team(username) |
| 691 | + if not team_owner: |
| 692 | + raise VenafiError(f"Unable to find identity [{username}]") |
| 693 | + owners_list.append(team_owner) |
| 694 | + return for_update, owners_list |
| 695 | + |
| 696 | + def resolve_user_to_cloud_owner(self, username): |
| 697 | + user = self.get_vaas_identity(username) |
| 698 | + if not user: |
| 699 | + return None |
| 700 | + owner = create_owner(OWNER_TYPE_USER, user.user_id) |
| 701 | + return owner |
| 702 | + |
| 703 | + def resolve_user_to_cloud_team(self, username): |
| 704 | + teams = list() |
| 705 | + data_teams = None |
| 706 | + try: |
| 707 | + status, response = self._get(URLS.TEAMS_ID) |
| 708 | + data_teams = response['teams'] |
| 709 | + except VenafiError as err: |
| 710 | + log.debug(f"Error while getting team [{username}]: {err.args[0]}") |
| 711 | + # date_teams will never be empty, we are always expecting at least one team |
| 712 | + for data in data_teams: |
| 713 | + team = build_team(data) |
| 714 | + teams.append(team) |
| 715 | + if len(teams) > 0: |
| 716 | + for team in teams: |
| 717 | + if team.name == username: |
| 718 | + owner = create_owner(OWNER_TYPE_TEAM, team.team_id) |
| 719 | + return owner |
| 720 | + return None |
| 721 | + |
| 722 | + def get_vaas_identity(self, username): |
| 723 | + if not username or username == "": |
| 724 | + raise VenafiError("Username cannot be empty") |
| 725 | + url = URLS.USERS_USERNAME.format(username) |
| 726 | + try: |
| 727 | + status, response = self._get(url) |
| 728 | + if status == HTTPStatus.NOT_FOUND: |
| 729 | + return None |
| 730 | + identities = response['users'][0] |
| 731 | + identity = build_user(identities) |
| 732 | + return identity |
| 733 | + except VenafiError as err: |
| 734 | + log.debug(f"Unable to find identity [{username}] of type USER: {err.args[0]}") |
| 735 | + |
| 736 | + def resolve_cloud_owners_names(self, zone): |
| 737 | + app_name, cit_alias = _parse_zone(zone) |
| 738 | + app_details = self._get_app_details_by_name(app_name) |
| 739 | + users_list = list() |
| 740 | + teams_response = list() |
| 741 | + for owner in app_details.owner_ids_and_types: |
| 742 | + if owner['ownerType'] == OWNER_TYPE_USER: |
| 743 | + status, data = self._get(URLS.USERS_ID.format(owner['ownerId'])) |
| 744 | + user = build_user(data) |
| 745 | + users_list.append(user.username) |
| 746 | + elif owner['ownerType'] == OWNER_TYPE_TEAM: |
| 747 | + if not teams_response: |
| 748 | + status, data = self._get(URLS.TEAMS_ID) |
| 749 | + data_team = data['teams'] |
| 750 | + for t in data_team: |
| 751 | + team = build_team(t) |
| 752 | + teams_response.append(team) |
| 753 | + if teams_response: |
| 754 | + for team in teams_response: |
| 755 | + if team.team_id == owner['ownerId']: |
| 756 | + users_list.append(team.name) |
| 757 | + return users_list |
| 758 | + |
647 | 759 | def _get_ca_details(self, ca_name): |
648 | 760 | """ |
649 | 761 | :param str ca_name: |
@@ -893,6 +1005,8 @@ def _get_policy(self, zone, subject_cn_to_str): |
893 | 1005 | raise VenafiError("Certificate Authority info not found") |
894 | 1006 |
|
895 | 1007 | ps = build_policy_spec(cit, info, subject_cn_to_str) |
| 1008 | + users_list = self.resolve_cloud_owners_names(zone) |
| 1009 | + ps.users = users_list |
896 | 1010 | return ps |
897 | 1011 |
|
898 | 1012 | def _get_dek_hash(self, cert_id): |
@@ -943,3 +1057,4 @@ def _retrieve_service_generated_cert(self, request, dek_info): |
943 | 1057 |
|
944 | 1058 | cert, chain, private_key = zip_to_pem(data, request.chain_option) |
945 | 1059 | return Certificate(cert=cert, chain=chain, key=private_key) |
| 1060 | + |
0 commit comments