예제 #1
0
def _get_contract_token_from_cloud_identity(cfg: config.UAConfig) -> str:
    """Detect cloud_type and request a contract token from identity info.

    :param cfg: a ``config.UAConfig`` instance

    :raise NonAutoAttachImageError: When not on an auto-attach image type.
    :raise UrlError: On unexpected connectivity issues to contract
        server or inability to access identity doc from metadata service.
    :raise ContractAPIError: On unexpected errors when talking to the contract
        server.

    :return: contract token obtained from identity doc
    """
    cloud_type = identity.get_cloud_type()
    if cloud_type not in ("aws", ):  # TODO(avoid hard-coding supported types)
        raise exceptions.NonAutoAttachImageError(
            ua_status.MESSAGE_UNSUPPORTED_AUTO_ATTACH_CLOUD_TYPE.format(
                cloud_type=cloud_type))
    instance = identity.cloud_instance_factory()
    contract_client = contract.UAContractClient(cfg)
    pkcs7 = instance.identity_doc
    try:
        # TODO(make this logic cloud-agnostic if possible)
        tokenResponse = contract_client.request_aws_contract_token(pkcs7)
    except contract.ContractAPIError as e:
        if contract.API_ERROR_MISSING_INSTANCE_INFORMATION in e:
            raise exceptions.NonAutoAttachImageError(
                ua_status.MESSAGE_UNSUPPORTED_AUTO_ATTACH)
        raise e
    return tokenResponse["contractToken"]
예제 #2
0
def _inform_ubuntu_pro_existence_if_applicable() -> None:
    """Alert the user when running UA on cloud with PRO support."""
    cloud_type, _ = get_cloud_type()
    if cloud_type in PRO_CLOUDS:
        print(
            messages.SECURITY_USE_PRO_TMPL.format(
                title=CLOUD_TYPE_TO_TITLE.get(cloud_type), cloud=cloud_type
            )
        )
예제 #3
0
    def _perform_enable(self, silent: bool = False) -> bool:
        cloud_type, error = get_cloud_type()
        if cloud_type is None and error == NoCloudTypeReason.CLOUD_ID_ERROR:
            logging.warning(
                "Could not determine cloud, "
                "defaulting to generic FIPS package."
            )
        if super()._perform_enable(silent=silent):
            self.cfg.remove_notice("", messages.FIPS_INSTALL_OUT_OF_DATE)
            return True

        return False
예제 #4
0
    def static_affordances(self) -> Tuple[StaticAffordance, ...]:
        cloud_titles = {"aws": "an AWS", "azure": "an Azure", "gce": "a GCP"}
        cloud_id, _ = get_cloud_type()
        if cloud_id is None:
            cloud_id = ""

        series = util.get_platform_info().get("series", "")
        blocked_message = messages.FIPS_BLOCK_ON_CLOUD.format(
            series=series.title(), cloud=cloud_titles.get(cloud_id)
        )
        return (
            (
                blocked_message,
                lambda: self._allow_fips_on_cloud_instance(series, cloud_id),
                True,
            ),
        )
예제 #5
0
    def _replace_metapackage_on_cloud_instance(
        self, packages: List[str]
    ) -> List[str]:
        """
        Identify correct metapackage to be used if in a cloud instance.

        Currently, the contract backend is not delivering the right
        metapackage on a Bionic Azure or AWS cloud instance. For those
        clouds, we have cloud specific fips metapackages and we should
        use them. We are now performing that correction here, but this
        is a temporary fix.
        """
        cfg_disable_fips_metapackage_override = util.is_config_value_true(
            config=self.cfg.cfg,
            path_to_value="features.disable_fips_metapackage_override",
        )

        if cfg_disable_fips_metapackage_override:
            return packages

        series = util.get_platform_info().get("series")
        if series not in ("bionic", "focal"):
            return packages

        cloud_id, _ = get_cloud_type()
        if cloud_id is None:
            cloud_id = ""

        cloud_match = re.match(r"^(?P<cloud>(azure|aws|gce)).*", cloud_id)
        cloud_id = cloud_match.group("cloud") if cloud_match else ""

        if cloud_id not in ("azure", "aws", "gce"):
            return packages

        cloud_id = "gcp" if cloud_id == "gce" else cloud_id
        cloud_metapkg = "ubuntu-{}-fips".format(cloud_id)
        # Replace only the ubuntu-fips meta package if exists
        return [
            cloud_metapkg if pkg == "ubuntu-fips" else pkg for pkg in packages
        ]
예제 #6
0
def apply_contract_overrides(orig_access: Dict[str, Any],
                             series: Optional[str] = None) -> None:
    """Apply series-specific overrides to an entitlement dict.

    This function mutates orig_access dict by applying any series-overrides to
    the top-level keys under 'entitlement'. The series-overrides are sparse
    and intended to supplement existing top-level dict values. So, sub-keys
    under the top-level directives, obligations and affordance sub-key values
    will be preserved if unspecified in series-overrides.

    To more clearly indicate that orig_access in memory has already had
    the overrides applied, the 'series' key is also removed from the
    orig_access dict.

    :param orig_access: Dict with original entitlement access details
    """
    from uaclient.clouds.identity import get_cloud_type

    if not all([isinstance(orig_access, dict), "entitlement" in orig_access]):
        raise RuntimeError(
            'Expected entitlement access dict. Missing "entitlement" key:'
            " {}".format(orig_access))

    series_name = get_platform_info()["series"] if series is None else series
    cloud_type, _ = get_cloud_type()
    orig_entitlement = orig_access.get("entitlement", {})

    overrides = _select_overrides(orig_entitlement, series_name, cloud_type)

    for _weight, overrides_to_apply in sorted(overrides.items()):
        for key, value in overrides_to_apply.items():
            current = orig_access["entitlement"].get(key)
            if isinstance(current, dict):
                # If the key already exists and is a dict,
                # update that dict using the override
                current.update(value)
            else:
                # Otherwise, replace it wholesale
                orig_access["entitlement"][key] = value
 def test_fallback_if_no_cloud_type_found(self,
                                          m_cloud_type_from_result_file,
                                          m_which):
     assert get_cloud_type() is None
 def test_fallback_to_get_cloud_type_from_result_file(
         self, m_subp, m_cloud_type_from_result_file):
     """Use cloud-id utility to discover cloud type."""
     assert "cloud9" == get_cloud_type()
     assert [mock.call()] == m_cloud_type_from_result_file.call_args_list
 def test_use_cloud_id_when_available(self, m_subp, m_which):
     """Use cloud-id utility to discover cloud type."""
     assert "somecloud" == get_cloud_type()
     assert [mock.call("cloud-id")] == m_which.call_args_list