Skip to content

Commit

Permalink
Merge branch 'release-1.33.2' into develop
Browse files Browse the repository at this point in the history
* release-1.33.2:
  Bumping version to 1.33.2
  Update to latest partitions and endpoints
  Update to latest models
  Intial implementation for S3Express
  Add pagination config for GetChatControlsConfiguration in qbusiness
  • Loading branch information
aws-sdk-python-automation committed Nov 28, 2023
2 parents acc5d1e + e8a9f38 commit febc9ea
Show file tree
Hide file tree
Showing 44 changed files with 23,188 additions and 960 deletions.
62 changes: 62 additions & 0 deletions .changes/1.33.2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
[
{
"category": "``accessanalyzer``",
"description": "This release adds support for external access findings for S3 directory buckets to help you easily identify cross-account access. Updated service API, documentation, and paginators.",
"type": "api-change"
},
{
"category": "``bedrock``",
"description": "This release adds support for customization types, model life cycle status and minor versions/aliases for model identifiers.",
"type": "api-change"
},
{
"category": "``bedrock-agent``",
"description": "This release introduces Agents for Amazon Bedrock",
"type": "api-change"
},
{
"category": "``bedrock-agent-runtime``",
"description": "This release introduces Agents for Amazon Bedrock Runtime",
"type": "api-change"
},
{
"category": "``bedrock-runtime``",
"description": "This release adds support for minor versions/aliases for invoke model identifier.",
"type": "api-change"
},
{
"category": "``connect``",
"description": "Added support for following capabilities: Amazon Connect's in-app, web, and video calling. Two-way SMS integrations. Contact Lens real-time chat analytics feature. Amazon Connect Analytics Datalake capability. Capability to configure real time chat rules.",
"type": "api-change"
},
{
"category": "``customer-profiles``",
"description": "This release introduces DetectProfileObjectType API to auto generate object type mapping.",
"type": "api-change"
},
{
"category": "``endpoint-rules``",
"description": "Update endpoint-rules client to latest version",
"type": "api-change"
},
{
"category": "``qbusiness``",
"description": "Amazon Q - a generative AI powered application that your employees can use to ask questions and get answers from knowledge spread across disparate content repositories, summarize reports, write articles, take actions, and much more - all within their company's connected content repositories.",
"type": "api-change"
},
{
"category": "``qconnect``",
"description": "Amazon Q in Connect, an LLM-enhanced evolution of Amazon Connect Wisdom. This release adds generative AI support to Amazon Q Connect QueryAssistant and GetRecommendations APIs.",
"type": "api-change"
},
{
"category": "``s3``",
"description": "Adds support for S3 Express One Zone.",
"type": "api-change"
},
{
"category": "``s3control``",
"description": "Adds support for S3 Express One Zone, and InvocationSchemaVersion 2.0 for S3 Batch Operations.",
"type": "api-change"
}
]
17 changes: 17 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@
CHANGELOG
=========

1.33.2
======

* api-change:``accessanalyzer``: This release adds support for external access findings for S3 directory buckets to help you easily identify cross-account access. Updated service API, documentation, and paginators.
* api-change:``bedrock``: This release adds support for customization types, model life cycle status and minor versions/aliases for model identifiers.
* api-change:``bedrock-agent``: This release introduces Agents for Amazon Bedrock
* api-change:``bedrock-agent-runtime``: This release introduces Agents for Amazon Bedrock Runtime
* api-change:``bedrock-runtime``: This release adds support for minor versions/aliases for invoke model identifier.
* api-change:``connect``: Added support for following capabilities: Amazon Connect's in-app, web, and video calling. Two-way SMS integrations. Contact Lens real-time chat analytics feature. Amazon Connect Analytics Datalake capability. Capability to configure real time chat rules.
* api-change:``customer-profiles``: This release introduces DetectProfileObjectType API to auto generate object type mapping.
* api-change:``endpoint-rules``: Update endpoint-rules client to latest version
* api-change:``qbusiness``: Amazon Q - a generative AI powered application that your employees can use to ask questions and get answers from knowledge spread across disparate content repositories, summarize reports, write articles, take actions, and much more - all within their company's connected content repositories.
* api-change:``qconnect``: Amazon Q in Connect, an LLM-enhanced evolution of Amazon Connect Wisdom. This release adds generative AI support to Amazon Q Connect QueryAssistant and GetRecommendations APIs.
* api-change:``s3``: Adds support for S3 Express One Zone.
* api-change:``s3control``: Adds support for S3 Express One Zone, and InvocationSchemaVersion 2.0 for S3 Batch Operations.


1.33.1
======

Expand Down
2 changes: 1 addition & 1 deletion botocore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import os
import re

__version__ = '1.33.1'
__version__ = '1.33.2'


class NullHandler(logging.Handler):
Expand Down
173 changes: 173 additions & 0 deletions botocore/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,176 @@ def _normalize_url_path(self, path):
return path


class S3ExpressAuth(S3SigV4Auth):
REQUIRES_IDENTITY_CACHE = True

def __init__(
self, credentials, service_name, region_name, *, identity_cache
):
super().__init__(credentials, service_name, region_name)
self._identity_cache = identity_cache

def add_auth(self, request):
super().add_auth(request)

def _modify_request_before_signing(self, request):
super()._modify_request_before_signing(request)
if 'x-amz-s3session-token' not in request.headers:
request.headers['x-amz-s3session-token'] = self.credentials.token
# S3Express does not support STS' X-Amz-Security-Token
if 'X-Amz-Security-Token' in request.headers:
del request.headers['X-Amz-Security-Token']


class S3ExpressPostAuth(S3ExpressAuth):
REQUIRES_IDENTITY_CACHE = True

def add_auth(self, request):
datetime_now = datetime.datetime.utcnow()
request.context['timestamp'] = datetime_now.strftime(SIGV4_TIMESTAMP)

fields = {}
if request.context.get('s3-presign-post-fields', None) is not None:
fields = request.context['s3-presign-post-fields']

policy = {}
conditions = []
if request.context.get('s3-presign-post-policy', None) is not None:
policy = request.context['s3-presign-post-policy']
if policy.get('conditions', None) is not None:
conditions = policy['conditions']

policy['conditions'] = conditions

fields['x-amz-algorithm'] = 'AWS4-HMAC-SHA256'
fields['x-amz-credential'] = self.scope(request)
fields['x-amz-date'] = request.context['timestamp']

conditions.append({'x-amz-algorithm': 'AWS4-HMAC-SHA256'})
conditions.append({'x-amz-credential': self.scope(request)})
conditions.append({'x-amz-date': request.context['timestamp']})

if self.credentials.token is not None:
fields['X-Amz-S3session-Token'] = self.credentials.token
conditions.append(
{'X-Amz-S3session-Token': self.credentials.token}
)

# Dump the base64 encoded policy into the fields dictionary.
fields['policy'] = base64.b64encode(
json.dumps(policy).encode('utf-8')
).decode('utf-8')

fields['x-amz-signature'] = self.signature(fields['policy'], request)

request.context['s3-presign-post-fields'] = fields
request.context['s3-presign-post-policy'] = policy


class S3ExpressQueryAuth(S3ExpressAuth):
DEFAULT_EXPIRES = 300
REQUIRES_IDENTITY_CACHE = True

def __init__(
self,
credentials,
service_name,
region_name,
*,
identity_cache,
expires=DEFAULT_EXPIRES,
):
super().__init__(
credentials,
service_name,
region_name,
identity_cache=identity_cache,
)
self._expires = expires

def _modify_request_before_signing(self, request):
# We automatically set this header, so if it's the auto-set value we
# want to get rid of it since it doesn't make sense for presigned urls.
content_type = request.headers.get('content-type')
blocklisted_content_type = (
'application/x-www-form-urlencoded; charset=utf-8'
)
if content_type == blocklisted_content_type:
del request.headers['content-type']

# Note that we're not including X-Amz-Signature.
# From the docs: "The Canonical Query String must include all the query
# parameters from the preceding table except for X-Amz-Signature.
signed_headers = self.signed_headers(self.headers_to_sign(request))

auth_params = {
'X-Amz-Algorithm': 'AWS4-HMAC-SHA256',
'X-Amz-Credential': self.scope(request),
'X-Amz-Date': request.context['timestamp'],
'X-Amz-Expires': self._expires,
'X-Amz-SignedHeaders': signed_headers,
}
if self.credentials.token is not None:
auth_params['X-Amz-S3session-Token'] = self.credentials.token
# Now parse the original query string to a dict, inject our new query
# params, and serialize back to a query string.
url_parts = urlsplit(request.url)
# parse_qs makes each value a list, but in our case we know we won't
# have repeated keys so we know we have single element lists which we
# can convert back to scalar values.
query_string_parts = parse_qs(url_parts.query, keep_blank_values=True)
query_dict = {k: v[0] for k, v in query_string_parts.items()}

if request.params:
query_dict.update(request.params)
request.params = {}
# The spec is particular about this. It *has* to be:
# https://<endpoint>?<operation params>&<auth params>
# You can't mix the two types of params together, i.e just keep doing
# new_query_params.update(op_params)
# new_query_params.update(auth_params)
# percent_encode_sequence(new_query_params)
operation_params = ''
if request.data:
# We also need to move the body params into the query string. To
# do this, we first have to convert it to a dict.
query_dict.update(_get_body_as_dict(request))
request.data = ''
if query_dict:
operation_params = percent_encode_sequence(query_dict) + '&'
new_query_string = (
f"{operation_params}{percent_encode_sequence(auth_params)}"
)
# url_parts is a tuple (and therefore immutable) so we need to create
# a new url_parts with the new query string.
# <part> - <index>
# scheme - 0
# netloc - 1
# path - 2
# query - 3 <-- we're replacing this.
# fragment - 4
p = url_parts
new_url_parts = (p[0], p[1], p[2], new_query_string, p[4])
request.url = urlunsplit(new_url_parts)

def _inject_signature_to_request(self, request, signature):
# Rather than calculating an "Authorization" header, for the query
# param quth, we just append an 'X-Amz-Signature' param to the end
# of the query string.
request.url += '&X-Amz-Signature=%s' % signature

def _normalize_url_path(self, path):
# For S3, we do not normalize the path.
return path

def payload(self, request):
# From the doc link above:
# "You don't include a payload hash in the Canonical Request, because
# when you create a presigned URL, you don't know anything about the
# payload. Instead, you use a constant string "UNSIGNED-PAYLOAD".
return UNSIGNED_PAYLOAD


class SigV4QueryAuth(SigV4Auth):
DEFAULT_EXPIRES = 3600

Expand Down Expand Up @@ -970,6 +1140,9 @@ def add_auth(self, request):
's3-query': HmacV1QueryAuth,
's3-presign-post': HmacV1PostAuth,
's3v4-presign-post': S3SigV4PostAuth,
'v4-s3express': S3ExpressAuth,
'v4-s3express-query': S3ExpressQueryAuth,
'v4-s3express-presign-post': S3ExpressPostAuth,
'bearer': BearerAuth,
}

Expand Down
32 changes: 30 additions & 2 deletions botocore/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from botocore.awsrequest import prepare_request_dict
from botocore.compress import maybe_compress_request
from botocore.config import Config
from botocore.credentials import RefreshableCredentials
from botocore.discovery import (
EndpointDiscoveryHandler,
EndpointDiscoveryManager,
Expand Down Expand Up @@ -45,6 +46,7 @@
CachedProperty,
EventbridgeSignerSetter,
S3ControlArnParamHandlerv2,
S3ExpressIdentityResolver,
S3RegionRedirectorv2,
ensure_boolean,
get_service_module_name,
Expand Down Expand Up @@ -179,6 +181,7 @@ def create_client(
client_config=client_config,
scoped_config=scoped_config,
)
self._register_s3express_events(client=service_client)
self._register_s3_control_events(client=service_client)
self._register_endpoint_discovery(
service_client, endpoint_url, client_config
Expand Down Expand Up @@ -371,6 +374,18 @@ def _register_eventbridge_events(
endpoint_url=endpoint_url,
).register(client.meta.events)

def _register_s3express_events(
self,
client,
endpoint_bridge=None,
endpoint_url=None,
client_config=None,
scoped_config=None,
):
if client.meta.service_model.service_name != 's3':
return
S3ExpressIdentityResolver(client, RefreshableCredentials).register()

def _register_s3_events(
self,
client,
Expand Down Expand Up @@ -459,6 +474,9 @@ def _default_s3_presign_to_sigv2(self, signature_version, **kwargs):
if signature_version.startswith('v4a'):
return

if signature_version.startswith('v4-s3express'):
return f'{signature_version}'

for suffix in ['-query', '-presign-post']:
if signature_version.endswith(suffix):
return f's3{suffix}'
Expand Down Expand Up @@ -930,9 +948,17 @@ def _make_api_call(self, operation_name, api_params):
operation_model=operation_model,
context=request_context,
)
endpoint_url, additional_headers = self._resolve_endpoint_ruleset(
(
endpoint_url,
additional_headers,
properties,
) = self._resolve_endpoint_ruleset(
operation_model, api_params, request_context
)
if properties:
# Pass arbitrary endpoint info with the Request
# for use during construction.
request_context['endpoint_properties'] = properties
request_dict = self._convert_to_request_dict(
api_params=api_params,
operation_model=operation_model,
Expand Down Expand Up @@ -1075,6 +1101,7 @@ def _resolve_endpoint_ruleset(
if self._ruleset_resolver is None:
endpoint_url = self.meta.endpoint_url
additional_headers = {}
endpoint_properties = {}
else:
endpoint_info = self._ruleset_resolver.construct_endpoint(
operation_model=operation_model,
Expand All @@ -1083,6 +1110,7 @@ def _resolve_endpoint_ruleset(
)
endpoint_url = endpoint_info.url
additional_headers = endpoint_info.headers
endpoint_properties = endpoint_info.properties
# If authSchemes is present, overwrite default auth type and
# signing context derived from service model.
auth_schemes = endpoint_info.properties.get('authSchemes')
Expand All @@ -1099,7 +1127,7 @@ def _resolve_endpoint_ruleset(
else:
request_context['signing'] = signing_context

return endpoint_url, additional_headers
return endpoint_url, additional_headers, endpoint_properties

def get_paginator(self, operation_name):
"""Create a paginator for an operation.
Expand Down
Loading

0 comments on commit febc9ea

Please sign in to comment.