Skip to content

Commit a5a5477

Browse files
committed
pulling in main
2 parents c974e74 + 2718f5f commit a5a5477

File tree

12 files changed

+104
-186
lines changed

12 files changed

+104
-186
lines changed

infrastructure/stacks/networking/README.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,14 @@ For a high-level overview, see the [VPC Structure Confluence Page](https://nhsd-
4040

4141
### Public HTTPS Request Flow
4242

43-
1. External client makes HTTPS request → Internet Gateway
44-
2. Request routes to Load Balancer or API Gateway in public subnet
45-
3. Request forwards to Lambda (or other application) in private subnet
46-
4. Lambda processes the request and returns response
47-
5. Response returns to client through the same path
43+
1. External client makes HTTPS request to API Gateway
44+
2. Request forwards to Lambda (or other application) in private subnet
45+
3. Lambda processes the request and returns response
46+
4. Response returns to client through the same path
4847

4948
### Outbound Internet Access
5049

51-
- Lambda functions in private subnets can make outbound internet calls via NAT Gateways
52-
- No direct inbound access to Lambda from the internet
50+
- No direct inbound or outbound access to Lambda from the internet
5351

5452
### Internal-Only Traffic
5553

@@ -64,7 +62,6 @@ For a high-level overview, see the [VPC Structure Confluence Page](https://nhsd-
6462

6563
### Network ACLs
6664

67-
- **Public subnets:** Allow HTTP (80), HTTPS (443), ephemeral ports
6865
- **Private subnets:** Allow VPC traffic and responses to outbound requests
6966

7067
### Security Groups
@@ -74,8 +71,7 @@ For a high-level overview, see the [VPC Structure Confluence Page](https://nhsd-
7471

7572
### Route Tables
7673

77-
- **Public subnets:** Route to Internet Gateway for external access
78-
- **Private subnets:** Route to NAT Gateways for outbound-only access
74+
- **Private subnets:** Route to VPC Endpoints only
7975

8076
---
8177

infrastructure/stacks/networking/acm_certificates.tf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ resource "aws_acm_certificate" "domain_validation" {
2828
}
2929

3030
tags = {
31-
Region = local.region
32-
Stack = local.stack_name
33-
CerticateType = "DomainValidation"
31+
Region = local.region
32+
Stack = local.stack_name
33+
CertificateType = "DomainValidation"
3434
}
3535
}

infrastructure/stacks/networking/internet_gateway.tf

Lines changed: 0 additions & 7 deletions
This file was deleted.

infrastructure/stacks/networking/locals.tf

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
locals {
22
any_ip_cidr = "0.0.0.0/0"
33
vpc_cidr_block = "10.0.0.0/16"
4-
public_subnet_1_cidr = "10.0.3.0/24"
5-
public_subnet_2_cidr = "10.0.4.0/24"
6-
public_subnet_3_cidr = "10.0.5.0/24"
74
private_subnet_1_cidr = "10.0.6.0/24"
85
private_subnet_2_cidr = "10.0.7.0/24"
96
private_subnet_3_cidr = "10.0.8.0/24"

infrastructure/stacks/networking/network_acls.tf

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -42,68 +42,3 @@ resource "aws_network_acl" "private" {
4242
Stack = local.stack_name
4343
}
4444
}
45-
46-
# Network ACL for Public Subnets
47-
resource "aws_network_acl" "public" {
48-
vpc_id = aws_vpc.main.id
49-
subnet_ids = [
50-
aws_subnet.public_1.id,
51-
aws_subnet.public_2.id,
52-
aws_subnet.public_3.id
53-
]
54-
55-
# Allow all outbound traffic from public subnets
56-
egress {
57-
rule_no = 100
58-
action = "allow"
59-
cidr_block = "0.0.0.0/0"
60-
protocol = -1
61-
from_port = 0
62-
to_port = 0
63-
}
64-
65-
# Allow inbound HTTP
66-
ingress {
67-
rule_no = 100
68-
action = "allow"
69-
cidr_block = "0.0.0.0/0"
70-
protocol = "tcp"
71-
from_port = 80
72-
to_port = 80
73-
}
74-
75-
# Allow inbound HTTPS
76-
ingress {
77-
rule_no = 110
78-
action = "allow"
79-
cidr_block = "0.0.0.0/0"
80-
protocol = "tcp"
81-
from_port = 443
82-
to_port = 443
83-
}
84-
85-
# Allow responses to outbound requests (ephemeral ports)
86-
ingress {
87-
rule_no = 120
88-
action = "allow"
89-
cidr_block = "0.0.0.0/0"
90-
protocol = "tcp"
91-
from_port = 1024
92-
to_port = 65535
93-
}
94-
95-
# Allow inbound VPC traffic
96-
ingress {
97-
rule_no = 130
98-
action = "allow"
99-
cidr_block = local.vpc_cidr_block
100-
protocol = -1
101-
from_port = 0
102-
to_port = 0
103-
}
104-
105-
tags = {
106-
Name = "public-nacl",
107-
Stack = local.stack_name
108-
}
109-
}
Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,3 @@
1-
# Public Route Tables
2-
resource "aws_route_table" "public_1" {
3-
vpc_id = aws_vpc.main.id
4-
tags = {
5-
Name = "public-route-1",
6-
Stack = local.stack_name
7-
}
8-
}
9-
10-
resource "aws_route_table" "public_2" {
11-
vpc_id = aws_vpc.main.id
12-
tags = {
13-
Name = "public-route-2",
14-
Stack = local.stack_name
15-
}
16-
}
17-
18-
resource "aws_route_table" "public_3" {
19-
vpc_id = aws_vpc.main.id
20-
tags = {
21-
Name = "public-route-3",
22-
Stack = local.stack_name
23-
}
24-
}
25-
26-
# Associate Public Route Tables with Public Subnets
27-
resource "aws_route_table_association" "public_1" {
28-
subnet_id = aws_subnet.public_1.id
29-
route_table_id = aws_route_table.public_1.id
30-
}
31-
32-
resource "aws_route_table_association" "public_2" {
33-
subnet_id = aws_subnet.public_2.id
34-
route_table_id = aws_route_table.public_2.id
35-
}
36-
37-
resource "aws_route_table_association" "public_3" {
38-
subnet_id = aws_subnet.public_3.id
39-
route_table_id = aws_route_table.public_3.id
40-
}
41-
421
# Private Route Tables
432
resource "aws_route_table" "private_1" {
443
vpc_id = aws_vpc.main.id
@@ -79,22 +38,3 @@ resource "aws_route_table_association" "private_association_3" {
7938
subnet_id = aws_subnet.private_3.id
8039
route_table_id = aws_route_table.private_3.id
8140
}
82-
83-
# Egress Internet Access
84-
resource "aws_route" "public_internet_access" {
85-
route_table_id = aws_route_table.public_1.id
86-
destination_cidr_block = local.any_ip_cidr
87-
gateway_id = aws_internet_gateway.vpc_external_access.id
88-
}
89-
90-
resource "aws_route" "public_internet_access_2" {
91-
route_table_id = aws_route_table.public_2.id
92-
destination_cidr_block = local.any_ip_cidr
93-
gateway_id = aws_internet_gateway.vpc_external_access.id
94-
}
95-
96-
resource "aws_route" "public_internet_access_3" {
97-
route_table_id = aws_route_table.public_3.id
98-
destination_cidr_block = local.any_ip_cidr
99-
gateway_id = aws_internet_gateway.vpc_external_access.id
100-
}

infrastructure/stacks/networking/subnets.tf

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,3 @@
1-
# Public Subnets
2-
resource "aws_subnet" "public_1" {
3-
vpc_id = aws_vpc.main.id
4-
cidr_block = local.public_subnet_1_cidr
5-
availability_zone = local.availability_zone_1
6-
map_public_ip_on_launch = false
7-
tags = {
8-
Name = "public-subnet-1",
9-
Stack = local.stack_name
10-
}
11-
}
12-
13-
resource "aws_subnet" "public_2" {
14-
vpc_id = aws_vpc.main.id
15-
cidr_block = local.public_subnet_2_cidr
16-
availability_zone = local.availability_zone_2
17-
map_public_ip_on_launch = false
18-
tags = {
19-
Name = "public-subnet-2",
20-
Stack = local.stack_name
21-
}
22-
}
23-
24-
resource "aws_subnet" "public_3" {
25-
vpc_id = aws_vpc.main.id
26-
cidr_block = local.public_subnet_3_cidr
27-
availability_zone = local.availability_zone_3
28-
map_public_ip_on_launch = false
29-
tags = {
30-
Name = "public-subnet-3",
31-
Stack = local.stack_name
32-
}
33-
}
34-
351
# Private Subnets
362
resource "aws_subnet" "private_1" {
373
vpc_id = aws_vpc.main.id

src/eligibility_signposting_api/model/rules.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
StartDate = NewType("StartDate", date)
3030
EndDate = NewType("EndDate", date)
3131
CohortLabel = NewType("CohortLabel", str)
32+
RuleStop = NewType("RuleStop", bool)
3233

3334

3435
class RuleType(StrEnum):
@@ -99,6 +100,13 @@ class IterationRule(BaseModel):
99100
operator: RuleOperator = Field(..., alias="Operator")
100101
comparator: RuleComparator = Field(..., alias="Comparator")
101102
attribute_target: RuleAttributeTarget | None = Field(None, alias="AttributeTarget")
103+
rule_stop: RuleStop = Field(RuleStop(False), alias="RuleStop") # noqa: FBT003
104+
105+
@field_validator("rule_stop", mode="before")
106+
def parse_yn_to_bool(cls, v: str | bool) -> bool: # noqa: N805
107+
if isinstance(v, str):
108+
return v.upper() == "Y"
109+
return v
102110

103111
model_config = {"populate_by_name": True, "extra": "ignore"}
104112

src/eligibility_signposting_api/services/calculators/eligibility_calculator.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,15 @@ def evaluate_eligibility_by_iteration_rules(
106106
exclusion_reasons, actionable_reasons = [], []
107107
by_priority = sorted(iteration.iteration_rules, key=priority_getter)
108108
for _, rule_group in groupby(by_priority, key=priority_getter):
109-
status, group_actionable, group_exclusions = self.evaluate_priority_group(rule_group, worst_status)
109+
status, group_actionable, group_exclusions, is_rule_stop = self.evaluate_priority_group(
110+
rule_group, worst_status
111+
)
110112
# Merge results
111113
worst_status = status
112114
actionable_reasons.extend(group_actionable)
113115
exclusion_reasons.extend(group_exclusions)
116+
if is_rule_stop:
117+
break
114118
condition_status_entry = status_with_reasons.setdefault(worst_status, [])
115119
condition_status_entry.extend(
116120
actionable_reasons if worst_status is eligibility.Status.actionable else exclusion_reasons
@@ -124,9 +128,9 @@ def evaluate_priority_group(
124128
self,
125129
iteration_rule_group: Iterator[rules.IterationRule],
126130
worst_status_so_far_for_condition: eligibility.Status,
127-
) -> tuple[eligibility.Status, list[eligibility.Reason], list[eligibility.Reason]]:
131+
) -> tuple[eligibility.Status, list[eligibility.Reason], list[eligibility.Reason], bool]:
132+
is_rule_stop = False
128133
exclusion_reasons, actionable_reasons = [], []
129-
130134
exclude_capable_rules = [
131135
ir
132136
for ir in iteration_rule_group
@@ -147,4 +151,6 @@ def evaluate_priority_group(
147151
actionable_reasons.append(reason)
148152

149153
worst_group_status = eligibility.Status.worst(best_status, worst_status_so_far_for_condition)
150-
return worst_group_status, actionable_reasons, exclusion_reasons
154+
if worst_group_status.is_exclusion:
155+
is_rule_stop = any(rule.rule_stop for rule in exclude_capable_rules)
156+
return worst_group_status, actionable_reasons, exclusion_reasons, is_rule_stop

tests/fixtures/builders/model/rule.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class IterationCohortFactory(ModelFactory[rules.IterationCohort]): ...
2222
class IterationRuleFactory(ModelFactory[rules.IterationRule]):
2323
attribute_target = None
2424
cohort_label = None
25+
rule_stop = False
2526

2627

2728
class IterationFactory(ModelFactory[rules.Iteration]):

0 commit comments

Comments
 (0)