|
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) |
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 | +from .vaas_utils import AppDetails, OwnerIdsAndTypes, RecommendedSettings, EdgeEncryptionKey, zip_to_pem, value_matches_regex |
39 | 39 |
|
40 | 40 | TOKEN_HEADER_NAME = "tppl-api-key" # nosec |
41 | 41 | APPLICATION_SERVER_TYPE_ID = "784938d1-ef0d-11eb-9461-7bb533ba575b" |
|
50 | 50 | CSR_ATTR_COUNTRY = 'country' |
51 | 51 | CSR_ATTR_SANS_BY_TYPE = 'subjectAlternativeNamesByType' |
52 | 52 | CSR_ATTR_SANS_DNS = 'dnsNames' |
| 53 | +OWNER_TYPE_USER = "USER" |
| 54 | +OWNER_TYPE_TEAM = "TEAM" |
53 | 55 |
|
54 | 56 | log = get_child("connection-vaas") |
55 | 57 |
|
@@ -87,6 +89,9 @@ def __init__(self): |
87 | 89 | ISSUING_TEMPLATES_UPDATE = ISSUING_TEMPLATES + "/{}" |
88 | 90 | USER_ACCOUNTS = API_VERSION + "useraccounts" |
89 | 91 | DEK_PUBLIC_KEY = API_VERSION + "edgeencryptionkeys/{}" |
| 92 | + USERS_USERNAME = API_VERSION + "users/username/{}" |
| 93 | + USERS_ID = API_VERSION + "users/{}" |
| 94 | + TEAMS_ID = API_VERSION + "teams" |
90 | 95 |
|
91 | 96 |
|
92 | 97 | class CondorChainOptions: |
@@ -119,6 +124,16 @@ def _parse_zone(zone): |
119 | 124 | return app_name, cit_alias |
120 | 125 |
|
121 | 126 |
|
| 127 | +def create_owner(owner_type, owner_id): |
| 128 | + owner = OwnerIdsAndTypes(owner_type, owner_id) |
| 129 | + return owner |
| 130 | + |
| 131 | + |
| 132 | +def resolve_apikey_owner(user_details): |
| 133 | + owner = create_owner(OWNER_TYPE_USER, user_details.user.user_id) |
| 134 | + return owner |
| 135 | + |
| 136 | + |
122 | 137 | class CloudConnection(CommonConnection): |
123 | 138 | def __init__(self, token, url=None, http_request_kwargs=None): |
124 | 139 | super().__init__() |
@@ -607,22 +622,118 @@ def set_policy(self, zone, policy_spec): |
607 | 622 | raise VenafiError('User Details not found') |
608 | 623 |
|
609 | 624 | app_details = self._get_app_details_by_name(app_name) |
| 625 | + for_update, owners_list = self.resolve_owners(policy_spec.users, user_details) |
610 | 626 | if app_details: |
611 | | - # Application exists. Update with cit |
612 | | - if not self._policy_exists(zone): |
| 627 | + # Application exists. Update with cit and owners |
| 628 | + if for_update and len(policy_spec.users) == 0: |
| 629 | + log.debug("No users provided in the policy specification") |
| 630 | + else: |
| 631 | + owner_list = build_owner_json(owners_list) |
| 632 | + app_details.owner_ids_and_types = owner_list |
| 633 | + if app_details.cit_alias_id_map: |
613 | 634 | # Only link cit with Application when cit is not already associated with Application |
614 | | - app_req = build_app_update_request(app_details, resp_cit_data) |
615 | | - status, data = self._put(URLS.APP_BY_ID.format(app_details.app_id), app_req) |
616 | | - if status != HTTPStatus.OK: |
617 | | - raise VenafiError(f"Could not update Application [{app_name}] with cit [{resp_cit_data}]") |
| 635 | + cit_map = app_details.cit_alias_id_map |
| 636 | + cit_id, cit_name = get_cit_data_from_response(cit_data) |
| 637 | + cit_map[cit_name] = cit_id |
| 638 | + app_req = build_app_update_request(app_details, cit_map) |
| 639 | + status, data = self._put(URLS.APP_BY_ID.format(app_details.app_id), app_req) |
| 640 | + if status != HTTPStatus.OK: |
| 641 | + raise VenafiError(f"Could not update Application [{app_name}] with cit [{resp_cit_data}]") |
618 | 642 | else: |
619 | 643 | # Application does not exist. Create one |
620 | | - app_req = build_app_create_request(app_name, user_details, resp_cit_data) |
| 644 | + app_req = build_app_create_request(app_name, owners_list, resp_cit_data) |
621 | 645 | status, data = self._post(URLS.APPLICATIONS, app_req) |
622 | 646 | if status != HTTPStatus.CREATED: |
623 | 647 | raise VenafiError(f"Could not create application [{app_name}]") |
624 | 648 | return |
625 | 649 |
|
| 650 | + def resolve_owners(self, users_list, user_details): |
| 651 | + owners_list = list() |
| 652 | + for_update = False |
| 653 | + if not users_list: |
| 654 | + # When no users are provided on the list, adds apikey user as owner |
| 655 | + api_owner = resolve_apikey_owner(user_details) |
| 656 | + owners_list.append(api_owner) |
| 657 | + for_update = True |
| 658 | + else: |
| 659 | + # Resolving the usernames list |
| 660 | + # Creating a higher level Teams object to cache the response |
| 661 | + teams_list = list() |
| 662 | + users_list = list(set(users_list)) |
| 663 | + for username in users_list: |
| 664 | + cloud_owner = self.resolve_user_to_cloud_owner(username) |
| 665 | + if cloud_owner: |
| 666 | + owners_list.append(cloud_owner) |
| 667 | + else: |
| 668 | + team_owner = self.resolve_user_to_cloud_team(username) |
| 669 | + if not team_owner: |
| 670 | + raise VenafiError(f"Unable to find identity [{username}]") |
| 671 | + owners_list.append(team_owner) |
| 672 | + return for_update, owners_list |
| 673 | + |
| 674 | + def resolve_user_to_cloud_owner(self, username): |
| 675 | + user = self.get_vaas_identity(username) |
| 676 | + if not user: |
| 677 | + return None |
| 678 | + owner = create_owner(OWNER_TYPE_USER, user.user_id) |
| 679 | + return owner |
| 680 | + |
| 681 | + def resolve_user_to_cloud_team(self, username): |
| 682 | + teams = list() |
| 683 | + data_teams = None |
| 684 | + try: |
| 685 | + status, response = self._get(URLS.TEAMS_ID) |
| 686 | + data_teams = response['teams'] |
| 687 | + except VenafiError as err: |
| 688 | + log.debug(f"Error while getting team [{username}]: {err.args[0]}") |
| 689 | + # date_teams will never be empty, we are always expecting at least one team |
| 690 | + for data in data_teams: |
| 691 | + team = build_team(data) |
| 692 | + teams.append(team) |
| 693 | + if len(teams) > 0: |
| 694 | + for team in teams: |
| 695 | + if team.name == username: |
| 696 | + owner = create_owner(OWNER_TYPE_TEAM, team.team_id) |
| 697 | + return owner |
| 698 | + return None |
| 699 | + |
| 700 | + def get_vaas_identity(self, username): |
| 701 | + if not username or username == "": |
| 702 | + raise VenafiError("Username cannot be empty") |
| 703 | + url = URLS.USERS_USERNAME.format(username) |
| 704 | + try: |
| 705 | + status, response = self._get(url) |
| 706 | + if status == HTTPStatus.NOT_FOUND: |
| 707 | + return None |
| 708 | + identities = response['users'][0] |
| 709 | + identity = build_user(identities) |
| 710 | + return identity |
| 711 | + except VenafiError as err: |
| 712 | + log.debug(f"Unable to find identity [{username}] of type USER: {err.args[0]}") |
| 713 | + |
| 714 | + def resolve_cloud_owners_names(self, zone): |
| 715 | + app_name, cit_alias = _parse_zone(zone) |
| 716 | + app_details = self._get_app_details_by_name(app_name) |
| 717 | + users_list = list() |
| 718 | + teams_response = list() |
| 719 | + for owner in app_details.owner_ids_and_types: |
| 720 | + if owner['ownerType'] == OWNER_TYPE_USER: |
| 721 | + status, data = self._get(URLS.USERS_ID.format(owner['ownerId'])) |
| 722 | + user = build_user(data) |
| 723 | + users_list.append(user.username) |
| 724 | + elif owner['ownerType'] == OWNER_TYPE_TEAM: |
| 725 | + if not teams_response: |
| 726 | + status, data = self._get(URLS.TEAMS_ID) |
| 727 | + data_team = data['teams'] |
| 728 | + for t in data_team: |
| 729 | + team = build_team(t) |
| 730 | + teams_response.append(team) |
| 731 | + if teams_response: |
| 732 | + for team in teams_response: |
| 733 | + if team.team_id == owner['ownerId']: |
| 734 | + users_list.append(team.name) |
| 735 | + return users_list |
| 736 | + |
626 | 737 | def _get_ca_details(self, ca_name): |
627 | 738 | """ |
628 | 739 | :param str ca_name: |
@@ -825,6 +936,8 @@ def _get_policy(self, zone, subject_cn_to_str): |
825 | 936 | raise VenafiError("Certificate Authority info not found") |
826 | 937 |
|
827 | 938 | ps = build_policy_spec(cit, info, subject_cn_to_str) |
| 939 | + users_list = self.resolve_cloud_owners_names(zone) |
| 940 | + ps.users = users_list |
828 | 941 | return ps |
829 | 942 |
|
830 | 943 | def _get_dek_hash(self, cert_id): |
@@ -875,3 +988,4 @@ def _retrieve_service_generated_cert(self, request, dek_info): |
875 | 988 |
|
876 | 989 | cert, chain, private_key = zip_to_pem(data, request.chain_option) |
877 | 990 | return Certificate(cert=cert, chain=chain, key=private_key) |
| 991 | + |
0 commit comments