clear-skies-aws 2.0.4__py3-none-any.whl → 2.0.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clear-skies-aws
3
- Version: 2.0.4
3
+ Version: 2.0.6
4
4
  Summary: clearskies bindings for working in AWS
5
5
  Project-URL: Repository, https://github.com/clearskies-py/clearskies-aws
6
6
  Project-URL: Issues, https://github.com/clearskies-py/clearskies-aws/issues
@@ -22,7 +22,7 @@ Provides-Extra: akeyless
22
22
  Requires-Dist: akeyless-cloud-id<0.5.0,>=0.2.3; extra == 'akeyless'
23
23
  Requires-Dist: akeyless<6.0.0,>=5.0.0; extra == 'akeyless'
24
24
  Provides-Extra: mysql
25
- Requires-Dist: pymysql<2.0.0,>=1.1.0; extra == 'mysql'
25
+ Requires-Dist: clear-skies[mysql]; extra == 'mysql'
26
26
  Provides-Extra: ses
27
27
  Requires-Dist: jinja2<4.0.0,>=3.1.2; extra == 'ses'
28
28
  Description-Content-Type: text/markdown
@@ -1,4 +1,4 @@
1
- clearskies_aws/__init__.py,sha256=o83_Jk53zPtFz-zYfJVtbwfw2NdATRziR0tvRijnxVs,396
1
+ clearskies_aws/__init__.py,sha256=jCD6EjW-ZOE3xm_nAw2QarKynnwOdsTSnvfa6oXelGQ,366
2
2
  clearskies_aws/actions/__init__.py,sha256=YsIi3ZTdByu4R7I77uOAXDE5hzB31J_tRrIoTxe_bjo,371
3
3
  clearskies_aws/actions/action_aws.py,sha256=JMogBFIrN72h5oBQLbyMy0LmfVLrqvWCYLQDml1qO4M,4674
4
4
  clearskies_aws/actions/assume_role.py,sha256=XNxbVju460aBMS8NQhY80eoNVQgZRJ6-OydsNOx3neA,4319
@@ -22,9 +22,10 @@ clearskies_aws/contexts/lambda_invoke.py,sha256=hvW05FtyiraAvhQiP5DX77LhYoRMgFTY
22
22
  clearskies_aws/contexts/lambda_sns.py,sha256=_TyPqRWosfaJzreYGNabvR-XTLYYO4eVWMVINSIY-OE,4129
23
23
  clearskies_aws/contexts/lambda_sqs_standard.py,sha256=sekaPlCRvuHk-E8ohfFQkC2gAfO-DnTC7uLiIKfGY0E,5293
24
24
  clearskies_aws/cursors/__init__.py,sha256=vy-WYxNEy5nd9fqY0En3T6WhE3omoV1tE-A5Uz26cCk,94
25
- clearskies_aws/cursors/iam/__init__.py,sha256=-0uOKKzWZrlnCzUNITleKyT0rl3cqoLEbPtVrAF46hI,143
26
- clearskies_aws/cursors/iam/rds_mysql.py,sha256=PlJv8PebCFq08iv8OYPkSNd4dRTZFQbBrDFdb3brK_M,5656
25
+ clearskies_aws/cursors/iam/__init__.py,sha256=dY410gfPoMXB42jhmamqD5IiCeopDnxr5wIibpqaYcY,127
26
+ clearskies_aws/cursors/iam/rds_mysql.py,sha256=bdAYTLg9t8DsoSi0otY9bmIgLCbrezczxd_3hWuEkeE,5639
27
27
  clearskies_aws/cursors/port_forwarding/__init__.py,sha256=LBcFYeIIfmGhxf3Ezn1KChOUdkpF5AjJL1xE_ak-x3s,78
28
+ clearskies_aws/cursors/port_forwarding/ssm.py,sha256=RJXU6meeX9GNSbcxTGf6c9LcI4I0_wvYHnS_DzRSEXM,4498
28
29
  clearskies_aws/di/__init__.py,sha256=pLHSIKxS1oELOgttRuwM0yXdJRxjZKXQ6tPxme2db0U,222
29
30
  clearskies_aws/di/aws_additional_config_auto_import.py,sha256=94h_YsPBcdwMhqn0VAAfId1jLL5vCsk76kUrr-6ET_U,1275
30
31
  clearskies_aws/di/inject/__init__.py,sha256=5_x5_BBQwC6J4k5YLdTm1DfIDM-95zXz1L5a1nMrlrY,186
@@ -61,7 +62,7 @@ clearskies_aws/secrets/additional_configs/iam_db_auth.py,sha256=PwyiLaacpRfhBKzQ
61
62
  clearskies_aws/secrets/additional_configs/iam_db_auth_with_ssm.py,sha256=ABY29X-YvrE6vvNo6kVdf4DqyRNq5cFR5SfK7MNkltE,3463
62
63
  clearskies_aws/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssh_cert_bastion.py,sha256=mLaplwvJLSbGh6oXgdOKL9Mv-6hLv5OUYCfEwHbHvLE,3700
63
64
  clearskies_aws/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssm_bastion.py,sha256=2VHOwto4I9gBwrpd2HGpL-Wr0T2S-jFjUhe2Ib8hNJ8,6596
64
- clear_skies_aws-2.0.4.dist-info/METADATA,sha256=CMTqizz2HDuJdsyuFSsUpS1gcbfhEuFHDfA-ejsrWAE,9087
65
- clear_skies_aws-2.0.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
66
- clear_skies_aws-2.0.4.dist-info/licenses/LICENSE,sha256=MkEX8JF8kZxdyBpTTcB0YTd-xZpWnHvbRlw-pQh8u58,1069
67
- clear_skies_aws-2.0.4.dist-info/RECORD,,
65
+ clear_skies_aws-2.0.6.dist-info/METADATA,sha256=IidH6WQFF7CUARhh69VvYOTYty62G4udnySWuPnGtt0,9084
66
+ clear_skies_aws-2.0.6.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
67
+ clear_skies_aws-2.0.6.dist-info/licenses/LICENSE,sha256=MkEX8JF8kZxdyBpTTcB0YTd-xZpWnHvbRlw-pQh8u58,1069
68
+ clear_skies_aws-2.0.6.dist-info/RECORD,,
@@ -7,7 +7,6 @@ from clearskies_aws import (
7
7
  cursors,
8
8
  di,
9
9
  endpoints,
10
- handlers,
11
10
  input_outputs,
12
11
  mocks,
13
12
  models,
@@ -21,7 +20,6 @@ __all__ = [
21
20
  "cursors",
22
21
  "di",
23
22
  "endpoints",
24
- "handlers",
25
23
  "input_outputs",
26
24
  "mocks",
27
25
  "models",
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
 
3
- from clearskies_aws.cursors.iam.rds_mysql import RdsMySql
3
+ from clearskies_aws.cursors.iam.rds_mysql import RdsMysql
4
4
 
5
5
  logging.getLogger(__name__)
6
6
 
7
- __all__ = ["RdsMySql", "MysqlWithSSM"]
7
+ __all__ = ["RdsMysql"]
@@ -29,12 +29,12 @@ from typing import Any
29
29
 
30
30
  import clearskies
31
31
  from clearskies import decorators
32
- from clearskies.cursors import Mysql as MysqlBase
32
+ from clearskies.cursors import Mysql
33
33
 
34
34
  from clearskies_aws.di import inject
35
35
 
36
36
 
37
- class RdsMySql(MysqlBase):
37
+ class RdsMysql(Mysql):
38
38
  """MySQL cursor with AWS RDS IAM DB authentication."""
39
39
 
40
40
  """Injected boto3 provider for AWS API access."""
@@ -0,0 +1,137 @@
1
+ import time
2
+
3
+ import clearskies.configs
4
+ from clearskies import decorators
5
+ from clearskies.cursors.port_forwarding.port_forwarder import PortForwarder
6
+
7
+ from clearskies_aws.di import inject
8
+
9
+
10
+ class Ssm(PortForwarder):
11
+ """
12
+ Port forwarder using AWS SSM Session Manager.
13
+
14
+ This class sets up a local port forwarding tunnel to a remote host using AWS SSM.
15
+ If instance_id is not provided, it will search for a running instance by Name tag.
16
+ """
17
+
18
+ """
19
+ The EC2 instance ID to connect to. If not provided, instance_name will be used to look up the instance.
20
+ """
21
+ instance_id = clearskies.configs.String(default=None)
22
+
23
+ """
24
+ The Name tag of the EC2 instance to search for if instance_id is not provided.
25
+ """
26
+ instance_name = clearskies.configs.String(default=None)
27
+
28
+ """
29
+ The remote port to forward to.
30
+ """
31
+ remote_port = clearskies.configs.Integer()
32
+
33
+ """
34
+ The local port to bind for the forwarding tunnel (default: 0, auto-selects a free port).
35
+ """
36
+ local_port = clearskies.configs.Integer(default=0)
37
+
38
+ """
39
+ AWS region.
40
+ """
41
+ region = clearskies.configs.String(default=None)
42
+
43
+ """
44
+ AWS CLI profile.
45
+ """
46
+ profile = clearskies.configs.String(default=None)
47
+
48
+ """
49
+ Boto3 session or client provider
50
+ """
51
+ boto3 = inject.Boto3()
52
+
53
+ @decorators.parameters_to_properties
54
+ def __init__(
55
+ self,
56
+ instance_id=None,
57
+ instance_name=None,
58
+ remote_port=None,
59
+ local_port=0,
60
+ region=None,
61
+ profile=None,
62
+ ):
63
+ self._proc = None
64
+ self.finalize_and_validate_configuration()
65
+
66
+ def setup(self, original_host: str, original_port: int) -> tuple[str, int]:
67
+ """
68
+ Establish the port forwarding tunnel and return the local endpoint.
69
+
70
+ If instance_id is not set, searches for a running instance by Name tag.
71
+
72
+ Returns:
73
+ A tuple containing the local host and local port to connect to (e.g., ("localhost", 12345)).
74
+ """
75
+ # Resolve instance_id if needed
76
+ if not self.instance_id and self.instance_name:
77
+ ec2_api = self.boto3.client("ec2", region_name=self.region)
78
+ running_instances = ec2_api.describe_instances(
79
+ Filters=[
80
+ {"Name": "tag:Name", "Values": [self.instance_name]},
81
+ {"Name": "instance-state-name", "Values": ["running"]},
82
+ ]
83
+ )
84
+ instance_ids = []
85
+ for reservation in running_instances["Reservations"]:
86
+ for instance in reservation["Instances"]:
87
+ instance_ids.append(instance["InstanceId"])
88
+ if len(instance_ids) == 0:
89
+ raise ValueError("Failed to launch SSM tunnel! Cannot find bastion!")
90
+ self.instance_id = instance_ids.pop()
91
+
92
+ if self.local_port == 0:
93
+ self.local_port = self.pick_free_port("127.0.0.1")
94
+
95
+ if self.is_port_open("127.0.0.1", self.local_port):
96
+ return "127.0.0.1", self.local_port
97
+
98
+ ssm_cmd = [
99
+ "aws",
100
+ "ssm",
101
+ "start-session",
102
+ "--target",
103
+ self.instance_id,
104
+ "--document-name",
105
+ "AWS-StartPortForwardingSession",
106
+ "--parameters",
107
+ f"portNumber={self.remote_port},localPort={self.local_port}",
108
+ ]
109
+ if self.region:
110
+ ssm_cmd += ["--region", self.region]
111
+ if self.profile:
112
+ ssm_cmd += ["--profile", self.profile]
113
+
114
+ self._proc = self.subprocess.Popen(ssm_cmd, stdout=self.subprocess.PIPE, stderr=self.subprocess.PIPE)
115
+
116
+ start = time.time()
117
+ while True:
118
+ try:
119
+ test_sock = self.socket.socket(self.socket.AF_INET, self.socket.SOCK_STREAM)
120
+ test_sock.settimeout(0.2)
121
+ test_sock.connect(("127.0.0.1", self.local_port))
122
+ test_sock.close()
123
+ break
124
+ except Exception:
125
+ if self._proc is not None and self._proc.poll() is not None:
126
+ raise RuntimeError("SSM process exited unexpectedly")
127
+ if time.time() - start > 10:
128
+ raise TimeoutError(f"Timeout waiting for port {self.local_port} to open")
129
+ time.sleep(0.1)
130
+
131
+ return "127.0.0.1", self.local_port
132
+
133
+ def teardown(self):
134
+ if self._proc:
135
+ self._proc.terminate()
136
+ self._proc.wait()
137
+ self._proc = None