diff --git a/docs/requirements.rst b/docs/requirements.rst index 6ea7e25dba686b611fb61c5de902540fecc5210c..c6984e1b38e3be9899e79f282e5868ad32f406d0 100644 --- a/docs/requirements.rst +++ b/docs/requirements.rst @@ -60,3 +60,18 @@ Concrete Infrastructure Elements have a maps Association All elements in the active concretization are mapped to some abstract infrastructure element. Makes sure each concrete infrastructure element is mapped to a node in the Abstract Infrastructure Layer. + +Network Interfaces belong to a Security Group +--------------------------------------------- + + All network interfaces belong to a security group. + +Makes sure all network interfaces have been configured to belong to a security group. +This way, the user will be reminded to configure adequate rules for each network. + +External Services are reached through HTTPS +------------------------------------------- + + All external SaaS can be reached only through a secure connection. + +Makes sure that an HTTPS rule is enforced for a Network Interface of a Software Component that interfaces with a SaaS. \ No newline at end of file diff --git a/mc_openapi/doml_mc/common_reqs.py b/mc_openapi/doml_mc/common_reqs.py index e96aed0f66aa936bc321de59d5dd77449e2f49e5..eccb22dd1e0999b4a9bbe6b304645aa1d43225ac 100644 --- a/mc_openapi/doml_mc/common_reqs.py +++ b/mc_openapi/doml_mc/common_reqs.py @@ -1,3 +1,4 @@ +from re import M from typing import Optional from z3 import ( @@ -305,11 +306,32 @@ def iface_must_have_security_group(smtenc: SMTEncoding, smtsorts: SMTSorts) -> E return And( smtenc.element_class_fun(sg) == smtenc.classes["infrastructure_SecurityGroup"], Not(Exists([iface], - # smtenc.element_class_fun(iface) == smtenc.classes["infrastructure_NetworkInterface"], smtenc.association_rel(iface, smtenc.associations["infrastructure_NetworkInterface::associated"], sg) )) ) +# TODO: Check if HTTP should be disabled too +def external_services_must_have_https(smtenc: SMTEncoding, smtsorts: SMTSorts) -> ExprRef: + saas, sw_iface, sw_comp, deployment, ielem, net_iface, sec_group, rule = get_consts(smtsorts, + ["saas, sw_iface, sw_comp, deployment, ielem, net_iface, sec_group, rule"]) + return And( + smtenc.element_class_fun(saas) == smtenc.classes["application_SaaS"], + smtenc.element_class_fun(sec_group) == smtenc.classes["infrastructure_SecurityGroup"], + Not(Exists([sw_iface, sw_comp, deployment, ielem, net_iface, rule], + And( + smtenc.association_rel(saas, smtenc.associations["application_SaaS::exposedInterfaces"], sw_iface), + smtenc.association_rel(sw_comp, smtenc.associations["application_SoftwareComponent::consumedInterfaces"], sw_iface), + smtenc.association_rel(deployment, smtenc.associations["commons_Deployment::component"], sw_comp), + smtenc.association_rel(deployment, smtenc.associations["commons_Deployment::node"], ielem), + smtenc.association_rel(ielem, smtenc.associations["infrastructure_ComputingNode::ifaces"], net_iface), + smtenc.association_rel(net_iface, smtenc.associations["infrastructure_NetworkInterface::associated"], sec_group), + smtenc.association_rel(sec_group, smtenc.associations["infrastructure_SecurityGroup::rules"], rule), + smtenc.attribute_rel(rule, smtenc.attributes["infrastructure_Rule::fromPort"], smtsorts.attr_data_sort.int(443)), + smtenc.attribute_rel(rule, smtenc.attributes["infrastructure_Rule::toPort"], smtsorts.attr_data_sort.int(443)), + smtenc.attribute_rel(rule, smtenc.attributes["infrastructure_Rule::kind"], smtsorts.attr_data_sort.ss(smtenc.str_symbols["INGRESS"])) + ) + )) + ) # Error Descriptions @@ -402,6 +424,15 @@ def ed_iface_must_have_security_group(solver: Solver, smtsorts: SMTSorts, interm else: return "A network interface doesn't belong to any security group, or a security group is not associated with any network interface." +def ed_external_services_must_have_https(solver: Solver, smtsorts: SMTSorts, intermediate_model: IntermediateModel) -> str: + saas = Const("saas", smtsorts.element_sort) + saas_name = get_user_friendly_name(intermediate_model, solver.model(), saas) + + if saas_name: + return "A Security Group doesn't have a rule to access external service (SaaS) named '{saas_name}' through HTTPS (port 443)." + else: + return "A Security Group doesn't have a rule to access an external service (SaaS) through HTTPS (port 443)." + RequirementLists = { DOMLVersion.V1_0: [ (vm_iface, "vm_iface", "All virtual machines must be connected to at least one network interface.", ed_vm_iface), @@ -418,7 +449,8 @@ RequirementLists = { (all_SoftwareComponents_deployed, "all_SoftwareComponents_deployed", "All software components have been deployed to some node.", ed_all_SoftwareComponents_deployed), (all_infrastructure_elements_deployed, "all_infrastructure_elements_deployed", "All abstract infrastructure elements are mapped to an element in the active concretization.", ed_all_infrastructure_elements_deployed), (all_concrete_map_something, "all_concrete_map_something", "All elements in the active concretization are mapped to some abstract infrastructure element.", ed_all_concrete_map_something), - (iface_must_have_security_group, "iface_must_have_security_group", "All interfaces should have a security group.", ed_iface_must_have_security_group) + (iface_must_have_security_group, "iface_must_have_security_group", "All interfaces should have a security group.", ed_iface_must_have_security_group), + (external_services_must_have_https, "external_services_must_have_https", "All external SaaS should be accessed through HTTPS.", ed_external_services_must_have_https) ], DOMLVersion.V2_1: [ (vm_iface, "vm_iface", "All virtual machines must be connected to at least one network interface.", ed_vm_iface),