Woori FIS · AWS · Security
Woori Financial Group AWS security architecture
Moved network separation requirements across multiple AWS accounts into subnet and firewall structure, and standardized security settings as one set of Terraform code.
- Role
- Cloud Security Engineer · Information Security Department
- Period
- Feb 2026 – Oct 2026
- Cloud
- AWS
- Scale
- Multiple AWS accounts
- Key tech
- Terraform · AWS Network Firewall · AWS WAF · AWS Shield Standard · GuardDuty · Security Hub · Splunk · Python
- 5
- Security services connected to Splunk SIEM/SOAR
- 3
- Design principles from network separation
- 1
- Set of Terraform code across multiple AWS accounts
At a glance
Problem
Group companies were adopting public cloud for the first time, with no Terraform in place, and security settings varied by account and by person. Network separation rules were hard to hold in documents alone.
Approach
Network separation (a Korean financial regulation) became three design principles: separate DMZ and Private subnets, no public IP on backends, and outbound only to allowed destinations. WAF, Network Firewall, and Shield Standard are defined in Terraform and applied through the same code to every account, with GuardDuty and Security Hub connected to Splunk SIEM/SOAR.
Result
The same security standard repeats through code as accounts grow, and per-person differences are gone. A Python pipeline now collects and analyzes network configuration across multiple AWS accounts, so review is repeatable. IAM permissions are defined in Terraform as well, which structurally blocks excessive grants.
Up close
Computing network coverage (related public repository pf-09)
What this code does: Takes the target ranges to check and the CIDRs of the firewall rules, and returns only the ranges that no rule covers. It applies the rules one by one: a range that fits entirely inside a rule is dropped, a range that a rule covers only in part keeps just the uncovered remainder, and malformed CIDRs are skipped. An empty result means the requested traffic is already open, and anything left is exactly the range that still needs opening, so the decision needs no duplicate rules.
def uncovered_networks(
targets: Iterable[ipaddress.IPv4Network], rule_cidrs: Iterable[str]
) -> list[ipaddress.IPv4Network]:
"""The parts of the targets that no rule reaches."""
remaining = list(targets)
for cidr in rule_cidrs:
try:
rule = ipaddress.IPv4Network(cidr, strict=False)
except ValueError:
continue
next_round: list[ipaddress.IPv4Network] = []
for network in remaining:
if network.subnet_of(rule):
continue
if rule.subnet_of(network):
next_round.extend(network.address_exclude(rule))
else:
next_round.append(network)
remaining = next_round
return remainingWhat I learned
The biggest lesson was that once security settings become code, differences between accounts show up as differences in code. When each person configured accounts in the console, finding which account differed meant comparing settings one by one; applying the same Terraform code to every account made any difference visible right in the code. Rules that existed only on paper, such as network separation, could be enforced by structure only after they were turned into three principles: separate subnets, no public IPs on the backend, and outbound only to allowed destinations. I also learned that a standard defined in code is complete only when it is confirmed to hold in each account, and the pipeline that collects and analyzes network configuration was built to make that confirmation a repeatable check rather than something people remember.