Skip to content

Commit 850022d

Browse files
Merge branch 'release-1.44.77'
* release-1.44.77: Bumping version to 1.44.77 Update changelog based on model updates Tighten output file permissions (#10197)
2 parents 82c8a85 + bb780bb commit 850022d

10 files changed

Lines changed: 204 additions & 72 deletions

File tree

.changes/1.44.77.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[
2+
{
3+
"category": "``bcm-dashboards``",
4+
"description": "Scheduled email reports of Billing and Cost Management Dashboards",
5+
"type": "api-change"
6+
},
7+
{
8+
"category": "``bedrock-agentcore``",
9+
"description": "Introducing support for SearchRegistryRecords API on AgentCoreRegistry",
10+
"type": "api-change"
11+
},
12+
{
13+
"category": "``bedrock-agentcore-control``",
14+
"description": "Initial release for CRUDL in AgentCore Registry Service",
15+
"type": "api-change"
16+
},
17+
{
18+
"category": "``mediaconnect``",
19+
"description": "Adds support for MediaLive Channel-type Router Inputs.",
20+
"type": "api-change"
21+
},
22+
{
23+
"category": "``redshift-data``",
24+
"description": "The BatchExecuteStatement API now supports named SQL parameters, enabling secure batch queries with parameterized values. This enhancement helps prevent SQL injection vulnerabilities and improves query reusability.",
25+
"type": "api-change"
26+
},
27+
{
28+
"category": "``sagemaker``",
29+
"description": "Release support for g7e instance types for SageMaker HyperPod",
30+
"type": "api-change"
31+
},
32+
{
33+
"category": "s3, streaming output",
34+
"description": "Output files created by S3 Select and streaming output commands are now created with owner-only permissions (0600). Existing files are also tightened to 0600 when overwritten.",
35+
"type": "bugfix"
36+
}
37+
]

CHANGELOG.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@
22
CHANGELOG
33
=========
44

5+
1.44.77
6+
=======
7+
8+
* api-change:``bcm-dashboards``: Scheduled email reports of Billing and Cost Management Dashboards
9+
* api-change:``bedrock-agentcore``: Introducing support for SearchRegistryRecords API on AgentCoreRegistry
10+
* api-change:``bedrock-agentcore-control``: Initial release for CRUDL in AgentCore Registry Service
11+
* api-change:``mediaconnect``: Adds support for MediaLive Channel-type Router Inputs.
12+
* api-change:``redshift-data``: The BatchExecuteStatement API now supports named SQL parameters, enabling secure batch queries with parameterized values. This enhancement helps prevent SQL injection vulnerabilities and improves query reusability.
13+
* api-change:``sagemaker``: Release support for g7e instance types for SageMaker HyperPod
14+
* bugfix:s3, streaming output: Output files created by S3 Select and streaming output commands are now created with owner-only permissions (0600). Existing files are also tightened to 0600 when overwritten.
15+
16+
517
1.44.76
618
=======
719

awscli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import os
2020

21-
__version__ = '1.44.76'
21+
__version__ = '1.44.77'
2222

2323
#
2424
# Get our data path to be added to botocore's search path

awscli/customizations/s3events.py

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
# ANY KIND, either express or implied. See the License for the specific
1212
# language governing permissions and limitations under the License.
1313
"""Add S3 specific event streaming output arg."""
14-
from awscli.arguments import CustomArgument
1514

15+
import os
16+
17+
from awscli.arguments import CustomArgument
1618

1719
STREAM_HELP_TEXT = 'Filename where the records will be saved'
1820

@@ -24,26 +26,28 @@ class DocSectionNotFoundError(Exception):
2426
def register_event_stream_arg(event_handlers):
2527
event_handlers.register(
2628
'building-argument-table.s3api.select-object-content',
27-
add_event_stream_output_arg)
29+
add_event_stream_output_arg,
30+
)
2831
event_handlers.register_last(
29-
'doc-output.s3api.select-object-content',
30-
replace_event_stream_docs
32+
'doc-output.s3api.select-object-content', replace_event_stream_docs
3133
)
3234

3335

3436
def register_document_expires_string(event_handlers):
35-
event_handlers.register_last(
36-
'doc-output.s3api',
37-
document_expires_string
38-
)
37+
event_handlers.register_last('doc-output.s3api', document_expires_string)
3938

40-
def add_event_stream_output_arg(argument_table, operation_model,
41-
session, **kwargs):
39+
40+
def add_event_stream_output_arg(
41+
argument_table, operation_model, session, **kwargs
42+
):
4243
argument_table['outfile'] = S3SelectStreamOutputArgument(
43-
name='outfile', help_text=STREAM_HELP_TEXT,
44-
cli_type_name='string', positional_arg=True,
44+
name='outfile',
45+
help_text=STREAM_HELP_TEXT,
46+
cli_type_name='string',
47+
positional_arg=True,
4548
stream_key=operation_model.output_shape.serialization['payload'],
46-
session=session)
49+
session=session,
50+
)
4751

4852

4953
def replace_event_stream_docs(help_command, **kwargs):
@@ -56,11 +60,14 @@ def replace_event_stream_docs(help_command, **kwargs):
5660
# This should never happen, but in the rare case that it does
5761
# we should be raising something with a helpful error message.
5862
raise DocSectionNotFoundError(
59-
'Could not find the "output" section for the command: %s'
60-
% help_command)
63+
f'Could not find the "output" section for the command: {help_command}'
64+
)
6165
doc.write('======\nOutput\n======\n')
62-
doc.write("This command generates no output. The selected "
63-
"object content is written to the specified outfile.\n")
66+
doc.write(
67+
"This command generates no output. The selected "
68+
"object content is written to the specified outfile.\n"
69+
)
70+
6471

6572
def document_expires_string(help_command, **kwargs):
6673
doc = help_command.doc
@@ -78,7 +85,7 @@ def document_expires_string(help_command, **kwargs):
7885
f'\n\n{" " * doc.style.indentation * doc.style.indent_width}',
7986
'ExpiresString -> (string)\n\n',
8087
'\tThe raw, unparsed value of the ``Expires`` field.',
81-
f'\n\n{" " * doc.style.indentation * doc.style.indent_width}'
88+
f'\n\n{" " * doc.style.indentation * doc.style.indent_width}',
8289
]
8390

8491
for idx, write in enumerate(deprecation_note_and_expires_string):
@@ -91,7 +98,7 @@ class S3SelectStreamOutputArgument(CustomArgument):
9198
_DOCUMENT_AS_REQUIRED = True
9299

93100
def __init__(self, stream_key, session, **kwargs):
94-
super(S3SelectStreamOutputArgument, self).__init__(**kwargs)
101+
super().__init__(**kwargs)
95102
# This is the key in the response body where we can find the
96103
# streamed contents.
97104
self._stream_key = stream_key
@@ -100,8 +107,9 @@ def __init__(self, stream_key, session, **kwargs):
100107

101108
def add_to_params(self, parameters, value):
102109
self._output_file = value
103-
self._session.register('after-call.s3.SelectObjectContent',
104-
self.save_file)
110+
self._session.register(
111+
'after-call.s3.SelectObjectContent', self.save_file
112+
)
105113

106114
def save_file(self, parsed, **kwargs):
107115
# This method is hooked into after-call which fires
@@ -112,7 +120,11 @@ def save_file(self, parsed, **kwargs):
112120
if self._stream_key not in parsed:
113121
return
114122
event_stream = parsed[self._stream_key]
115-
with open(self._output_file, 'wb') as fp:
123+
fd = os.open(
124+
self._output_file, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600
125+
)
126+
os.chmod(self._output_file, 0o600)
127+
with os.fdopen(fd, 'wb') as fp:
116128
for event in event_stream:
117129
if 'Records' in event:
118130
fp.write(event['Records']['Payload'])

awscli/customizations/streamingoutputarg.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,26 @@
1010
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
1111
# ANY KIND, either express or implied. See the License for the specific
1212
# language governing permissions and limitations under the License.
13+
import os
14+
1315
from botocore.model import Shape
1416

1517
from awscli.arguments import BaseCLIArgument
1618

1719

18-
def add_streaming_output_arg(argument_table, operation_model,
19-
session, **kwargs):
20+
def add_streaming_output_arg(
21+
argument_table, operation_model, session, **kwargs
22+
):
2023
# Implementation detail: hooked up to 'building-argument-table'
2124
# event.
2225
if _has_streaming_output(operation_model):
2326
streaming_argument_name = _get_streaming_argument_name(operation_model)
2427
argument_table['outfile'] = StreamingOutputArgument(
2528
response_key=streaming_argument_name,
2629
operation_model=operation_model,
27-
session=session, name='outfile')
30+
session=session,
31+
name='outfile',
32+
)
2833

2934

3035
def _has_streaming_output(model):
@@ -36,15 +41,16 @@ def _get_streaming_argument_name(model):
3641

3742

3843
class StreamingOutputArgument(BaseCLIArgument):
39-
4044
BUFFER_SIZE = 32768
4145
HELP = 'Filename where the content will be saved'
4246

43-
def __init__(self, response_key, operation_model, name,
44-
session, buffer_size=None):
47+
def __init__(
48+
self, response_key, operation_model, name, session, buffer_size=None
49+
):
4550
self._name = name
46-
self.argument_model = Shape('StreamingOutputArgument',
47-
{'type': 'string'})
51+
self.argument_model = Shape(
52+
'StreamingOutputArgument', {'type': 'string'}
53+
)
4854
if buffer_size is None:
4955
buffer_size = self.BUFFER_SIZE
5056
self._buffer_size = buffer_size
@@ -81,15 +87,15 @@ def documentation(self):
8187
return self.HELP
8288

8389
def add_to_parser(self, parser):
84-
parser.add_argument(self._name, metavar=self.py_name,
85-
help=self.HELP)
90+
parser.add_argument(self._name, metavar=self.py_name, help=self.HELP)
8691

8792
def add_to_params(self, parameters, value):
8893
self._output_file = value
8994
service_id = self._operation_model.service_model.service_id.hyphenize()
9095
operation_name = self._operation_model.name
91-
self._session.register('after-call.%s.%s' % (
92-
service_id, operation_name), self.save_file)
96+
self._session.register(
97+
f'after-call.{service_id}.{operation_name}', self.save_file
98+
)
9399

94100
def save_file(self, parsed, **kwargs):
95101
if self._response_key not in parsed:
@@ -100,7 +106,11 @@ def save_file(self, parsed, **kwargs):
100106
return
101107
body = parsed[self._response_key]
102108
buffer_size = self._buffer_size
103-
with open(self._output_file, 'wb') as fp:
109+
fd = os.open(
110+
self._output_file, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600
111+
)
112+
os.chmod(self._output_file, 0o600)
113+
with os.fdopen(fd, 'wb') as fp:
104114
data = body.read(buffer_size)
105115
while data:
106116
fp.write(data)

doc/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
# The short X.Y version.
5353
version = '1.44.'
5454
# The full version, including alpha/beta/rc tags.
55-
release = '1.44.76'
55+
release = '1.44.77'
5656

5757
# The language for content autogenerated by Sphinx. Refer to documentation
5858
# for a list of supported languages.

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ universal = 0
33

44
[metadata]
55
requires_dist =
6-
botocore==1.42.86
6+
botocore==1.42.87
77
docutils>=0.18.1,<=0.19
88
s3transfer>=0.16.0,<0.17.0
99
PyYAML>=3.10,<6.1

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def find_version(*file_paths):
2424

2525

2626
install_requires = [
27-
'botocore==1.42.86',
27+
'botocore==1.42.87',
2828
'docutils>=0.18.1,<=0.19',
2929
's3transfer>=0.16.0,<0.17.0',
3030
'PyYAML>=3.10,<6.1',

0 commit comments

Comments
 (0)