Skip to content

Instantly share code, notes, and snippets.

@sivachandran
Created June 22, 2025 01:25
Show Gist options
  • Save sivachandran/b62c932ab331a256be5a261e870aa72e to your computer and use it in GitHub Desktop.
Save sivachandran/b62c932ab331a256be5a261e870aa72e to your computer and use it in GitHub Desktop.
Python script to update OCI security list to whitelist dynamic dns ip address for SSH access.
import socket
import oci
import sys
# === Config - Update these ===
DOMAIN_NAME = "example.com"
SECURITY_LIST_ID = "ocid1.securitylist.oc1..xxxxxx" # Replace with your Security List OCID
PORT = 22
PROTOCOL = "6" # TCP
DESCRIPTION = f"SSH access for {DOMAIN_NAME}"
def resolve_domain_to_ip(domain):
try:
ip = socket.gethostbyname(domain)
print(f"[+] Resolved {domain} to {ip}")
return ip
except socket.gaierror as e:
print(f"[-] Failed to resolve domain {domain}: {e}")
sys.exit(1)
def get_security_list(client, sec_list_id):
return client.get_security_list(sec_list_id).data
def find_rule_by_description(rules, description):
"""
Finds the ingress rule matching the description.
Returns the rule and its index.
"""
for idx, rule in enumerate(rules):
if rule.description == description:
return idx, rule
return None, None
def main():
ip = resolve_domain_to_ip(DOMAIN_NAME)
ip_cidr = f"{ip}/32"
signer = oci.auth.signers.InstancePrincipalsSecurityTokenSigner()
client = oci.core.VirtualNetworkClient(config={}, signer=signer)
sec_list = get_security_list(client, SECURITY_LIST_ID)
ingress_rules = list(sec_list.ingress_security_rules)
idx, existing_rule = find_rule_by_description(ingress_rules, DESCRIPTION)
if existing_rule:
if existing_rule.source == ip_cidr and existing_rule.protocol == PROTOCOL:
port_range = existing_rule.tcp_options.destination_port_range if existing_rule.tcp_options else None
if port_range and port_range.min == PORT and port_range.max == PORT:
print("[*] Existing rule with same IP and port found. No update needed.")
return
# IP changed — remove the old rule
print(f"[!] IP change detected. Removing old rule with source {existing_rule.source}")
ingress_rules.pop(idx)
# Add new rule with updated IP
new_rule = oci.core.models.IngressSecurityRule(
protocol=PROTOCOL,
source=ip_cidr,
source_type="CIDR_BLOCK",
tcp_options=oci.core.models.TcpOptions(
destination_port_range=oci.core.models.PortRange(min=PORT, max=PORT)
),
description=DESCRIPTION
)
ingress_rules.append(new_rule)
update_details = oci.core.models.UpdateSecurityListDetails(
ingress_security_rules=ingress_rules,
egress_security_rules=sec_list.egress_security_rules,
defined_tags=sec_list.defined_tags,
freeform_tags=sec_list.freeform_tags,
display_name=sec_list.display_name
)
client.update_security_list(
security_list_id=SECURITY_LIST_ID,
update_security_list_details=update_details
)
print(f"[+] Updated security list with new IP {ip_cidr} for description '{DESCRIPTION}'.")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment