Skip to content

Commit a3827ee

Browse files
updating port scan script
1 parent f44f406 commit a3827ee

File tree

3 files changed

+189
-4
lines changed

3 files changed

+189
-4
lines changed

jobs/account-port-scan/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ COPY requirements.txt ./
66
RUN pip install --upgrade pip && \
77
pip install --no-cache-dir -r requirements.txt
88

9-
COPY app.py ./app.py
9+
COPY port-scan-report.py ./app.py
1010
COPY logging.json ./logging.json
1111

1212
# Copy the entrypoint script and make it executable
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
#!/usr/bin/env python3
2+
# Author: Ryan Tiffany
3+
# Copyright (c) 2024
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
16+
# TODO: Add COS python module
17+
# TODO: Generate JSON file of open ports
18+
# TODO: Write JSON file to COS bucket
19+
20+
__author__ = 'ryantiffany'
21+
import sys
22+
import os
23+
import socket
24+
import logging
25+
import SoftLayer
26+
import ibm_vpc
27+
from ibm_cloud_sdk_core import ApiException
28+
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
29+
30+
"""
31+
Pull IBM Cloud API key from environment. If not set, raise an error.
32+
"""
33+
ibmcloud_api_key = os.environ.get('IBMCLOUD_API_KEY')
34+
if not ibmcloud_api_key:
35+
raise ValueError("IBMCLOUD_API_KEY environment variable not found")
36+
37+
"""
38+
Create an IAM authenticator object for use with the VPC API.
39+
"""
40+
authenticator = IAMAuthenticator(apikey=ibmcloud_api_key)
41+
42+
43+
def setup_logging(default_path='logging.json', default_level=logging.info, env_key='LOG_CFG'):
44+
"""
45+
Set up logging configuration and use logging.json to format logs
46+
"""
47+
path = default_path
48+
value = os.getenv(env_key, None)
49+
if value:
50+
path = value
51+
if os.path.exists(path):
52+
with open(path, 'rt') as f:
53+
config = json.load(f)
54+
logging.config.dictConfig(config)
55+
else:
56+
logging.basicConfig(level=default_level)
57+
58+
59+
def sl_iam_client():
60+
"""
61+
Create a SoftLayer client object using the IBM Cloud API key
62+
This function is used to authenticate to the SoftLayer API
63+
and interact with Classic resources.
64+
"""
65+
client = SoftLayer.create_client_from_env(
66+
username="apikey",
67+
api_key=ibmcloud_api_key
68+
)
69+
return client
70+
71+
72+
def get_regions():
73+
"""
74+
Retrieve a list of IBM Cloud VPC regions
75+
"""
76+
service = ibm_vpc.VpcV1(authenticator=authenticator)
77+
service.set_service_url('https://us-south.iaas.cloud.ibm.com/v1')
78+
try:
79+
response = service.list_regions().get_result()
80+
regions = response['regions']
81+
region_names = [region['name'] for region in regions]
82+
return region_names
83+
except ApiException as e:
84+
logging.error("Unable to retrieve regions: %s", e)
85+
sys.exit()
86+
87+
88+
def get_floating_ips():
89+
"""
90+
Retrieve a list of IBM Cloud VPC floating IPs across all regions
91+
"""
92+
floating_ips = []
93+
regions = get_regions()
94+
for region in regions:
95+
service = ibm_vpc.VpcV1(authenticator=authenticator)
96+
service.set_service_url(f'https://{region}.iaas.cloud.ibm.com/v1')
97+
response = service.list_floating_ips().get_result()
98+
for fip in response['floating_ips']:
99+
ip_address = fip['address']
100+
floating_ips.append(ip_address)
101+
return floating_ips
102+
103+
104+
def get_classic_infrastructure_instances():
105+
"""
106+
Retrieve of public IPs associated with classic
107+
infrastructure virtual guests
108+
"""
109+
classic_host_ips = []
110+
client = sl_iam_client()
111+
vms = client['Account'].getVirtualGuests()
112+
filtered_vms = [s for s in vms if s.get('primaryIpAddress')]
113+
114+
for vm in filtered_vms:
115+
classic_host_ips.append(vm['primaryIpAddress'])
116+
return classic_host_ips
117+
118+
119+
def get_classic_infrastructure_hardware():
120+
"""
121+
Retrieve of public IPs associated with classic
122+
bare metal servers and network gateways
123+
"""
124+
classic_host_ips = []
125+
client = sl_iam_client()
126+
bare_metals = client['Account'].getHardware()
127+
filtered_bms = [s for s in bare_metals if s.get('primaryIpAddress')]
128+
129+
for bare_metal in filtered_bms:
130+
classic_host_ips.append(bare_metal['primaryIpAddress'])
131+
return classic_host_ips
132+
133+
134+
def scan_top_ports(target):
135+
"""
136+
Scan the top ports on a target IP address
137+
"""
138+
open_ports = []
139+
top_ports = [21, 22, 25, 23, 3389]
140+
for port in top_ports:
141+
try:
142+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
143+
sock.settimeout(1)
144+
result = sock.connect_ex((target, port))
145+
if result == 0:
146+
open_ports.append(port)
147+
sock.close()
148+
except KeyboardInterrupt:
149+
sys.exit()
150+
except socket.error:
151+
pass
152+
return open_ports
153+
154+
155+
def main():
156+
"""
157+
Main function to scan IBM Cloud VPC and classic infrastructure
158+
"""
159+
print("Starting scan of floating IPs...")
160+
targets = get_floating_ips()
161+
for target in targets:
162+
open_ports = scan_top_ports(target)
163+
if open_ports:
164+
print(f"Open ports on {target}: {open_ports}")
165+
print("VPC Floating IP Scan complete.")
166+
167+
print("Starting scan on classic infrastructure virtual guests...")
168+
targets = get_classic_infrastructure_instances()
169+
for target in targets:
170+
open_ports = scan_top_ports(target)
171+
if open_ports:
172+
print(f"Open ports on {target}: {open_ports}")
173+
print("Classic Virtual Guests Scan complete.")
174+
175+
print("Starting scan on classic infrastructure bare metals...")
176+
targets = get_classic_infrastructure_hardware()
177+
for target in targets:
178+
open_ports = scan_top_ports(target)
179+
if open_ports:
180+
print(f"Open ports on {target}: {open_ports}")
181+
print("Classic Bare Metals Scan complete.")
182+
183+
184+
if __name__ == "__main__":
185+
main()

jobs/account-port-scan/app.py renamed to jobs/account-port-scan/port-scan-report.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ def get_regions():
7070
Retrieve a list of IBM Cloud VPC regions
7171
"""
7272
service = ibm_vpc.VpcV1(authenticator=authenticator)
73-
service.set_service_url(f'https://us-south.iaas.cloud.ibm.com/v1')
73+
service.set_service_url('https://us-south.iaas.cloud.ibm.com/v1')
7474
try:
7575
response = service.list_regions().get_result()
7676
regions = response['regions']
7777
region_names = [region['name'] for region in regions]
7878
return region_names
7979
except ApiException as e:
80-
logging.error("Unable to retrieve regions: {0}".format(e))
80+
logging.error("Unable to retrieve regions: %s", e)
8181
sys.exit()
8282

8383

@@ -92,7 +92,7 @@ def get_floating_ips():
9292
service.set_service_url(f'https://{region}.iaas.cloud.ibm.com/v1')
9393
response = service.list_floating_ips().get_result()
9494
for fip in response['floating_ips']:
95-
ip_address = fip['address']
95+
ip_address = fip['address']
9696
floating_ips.append(ip_address)
9797
return floating_ips
9898

0 commit comments

Comments
 (0)