Vert.x mail prefers XOAUTH2 whenever the server offers it, so against Gmail the
app password was sent as an OAuth token and refused (535 5.7.8). Limit the
relay to the password-based SASL methods.
Composite alarms from upstream (#6408) use SmithyValidationErrors for AWS's
validation messages, and their tests use the CfnStackWaits, PartitionCleanup
and ThreadStates test helpers and ReplacementCleanup.owedPhysicalIds. These
are copied from upstream as they were at that commit; none brings in other
behaviour.
* fix(cloudwatch): return empty CompositeAlarms and LogAlarms from DescribeAlarms
AWS sends every alarm collection even when it is empty. Floci only sent
MetricAlarms, so the AWS CLI's text output printed a leading None line
for each missing paginator result key.
Closes#6362
* test(cloudwatch): check empty alarm collections in sdk-test-python instead of bats
Drop the new AWS CLI bats file and assert the empty CompositeAlarms and
LogAlarms lists in the existing describe_alarms test, as boto3 leaves an
absent list out of the response.
(cherry picked from commit 42f5019231b446c727d6c94def9d1445263de2d7)
* fix(cloudwatch): reject PutMetricData datums without a MetricName
MetricName is the one required member of MetricDatum. The JSON handler
stored a nameless datum under an empty name, and the Query handler
treated a member without MetricName as the end of the list, silently
dropping it and every later datum while still storing the earlier ones.
Both handlers now reject a missing or empty MetricName in top-level
MetricData and in EntityMetricData[].MetricData with MissingParameter
(400), the error PutMetricData declares for a missing required input,
naming the offending member. A whitespace name is still accepted, since
AWS constrains MetricName only to 1 to 255 characters. Every datum is
validated before any is stored, so a rejected request leaves no state
behind. On Query, a member index with no keys at all still ends that
MetricData list.
* fix(cloudwatch): return MissingRequiredParameterException on JSON and CBOR
CloudWatch is awsQueryCompatible. MissingParameter is the awsQueryError
code of the MissingRequiredParameterException shape, so it belongs in the
Query <Code> and the x-amzn-query-error header, while a JSON 1.0 or CBOR
body's __type names the shape. With the code in __type the AWS SDK v2
raised a generic CloudWatchException instead of the modelled one.
A package-private CloudWatchMetricsException keeps the Query code as its
error code and overrides jsonType() with the shape name, the same split
SwfException makes. The shared query-code table in AwsException is left
alone because SQS reports MissingParameter as its JSON type.
(cherry picked from commit b8d87df05413ea8c4f9497fa05f388c19d4124ec)
The SNS alarm notification from upstream (#5918) looks up the region's display
name in AwsPartitions, which upstream added in a partition rework not taken
here. A table of the commercial regions' names gives the same Region field.
The CloudWatch Agent sends PutMetricData with an empty top-level
MetricData and every datum nested under EntityMetricData[].MetricData.
Both the JSON 1.0 handler (also reached by Smithy RPC v2 CBOR) and the
Query handler read only the top-level list, so the agent's metrics were
silently dropped.
Both handlers now append each EntityMetricData entry's datums to the
top-level ones and store them under the request Namespace, with the same
parsing as top-level datums. Entity and StrictEntityValidation are
accepted and ignored. The per-request INFO logs of the raw request and
parsed datums are lowered to a DEBUG count.
Fixes#6066
(cherry picked from commit 03f57303969561b049c3ebba38f1fd9d2b68df4c)
* fix(cloudwatch): raise ResourceNotFoundException when a tag operation names a resource that does not exist
TagResource, UntagResource and ListTagsForResource answered 200 for any ARN, so
tagging a typo'd or deleted alarm, dashboard or metric stream told the caller the
tag had been applied. AWS raises ResourceNotFoundException. All three operations
now resolve the ARN first and report a 404 when nothing answers to it.
The fix sits in the three services rather than in the handlers, because CloudWatch
Metrics serves these operations over both Query and JSON 1.1 and the two handlers
route to the same service methods. A handler-level check would have left the other
protocol still answering 200.
What the 200 was hiding is worth naming, because "return an error instead of 200"
understates it. The write path resolved the ARN and then did nothing with the miss:
tagResource and untagResource each ended in an ifPresent, so a tag against an
unknown ARN was discarded, and ListTagsForResource answered the empty map. So the
ARN was neither rejected nor recorded. Nothing was stored against a phantom
resource, which is the one mercy here, but a caller that wrote a tag and read back
an empty list had no way to tell "this resource has no tags" from "this resource
does not exist".
That is why ListTagsForResource is included rather than left alone. It is the one
operation whose answer changes for a caller doing a speculative list, and the one
whose leniency made the silent write survive a round trip. No test or caller in the
repository depended on the empty-map answer for an unknown ARN: the only internal
caller is CloudWatchDashboardCfnProvisioner.reconcileTags, and both of its call
sites pass an ARN that putDashboard has just returned.
The error code is ResourceNotFoundException, not the shorter ResourceNotFound that
GetDashboard, DeleteDashboards and SetAlarmState answer with. Those are two separate
shapes in the CloudWatch model, mapped to two exception classes by the SDK, and the
model declares the longer one on exactly these three operations.
CloudWatch Logs needed no change. Its own TagResource, UntagResource and
ListTagsForResource already resolve the log group and raise
ResourceNotFoundException, which the new test pins so the two halves of CloudWatch
tagging cannot diverge in the other direction.
* fix(cloudwatch): resolve a dashboard by either the regionless or the region-ful form of its ARN
Dashboards are a global resource and AWS documents their ARN without a region,
arn:aws:cloudwatch::<account-id>:dashboard/<dashboard-name>, on both the TagResource
and the ListTagsForResource pages. Floci mints a region-ful one. The dashboard
lookup now accepts both shapes deliberately, so a caller holding either resolves.
Accepting both is what stops the preceding commit regressing a caller that does the
documented thing. Until the tag operations raised on a miss, the divergence was
invisible on this path: the documented ARN matched no stored dashboard, and the
answer was a silent 200 with an empty tag map. Turning a miss into
ResourceNotFoundException would have turned that into a hard 404 for a dashboard
that exists.
Only an absent region stands in for the dashboard's own, so an ARN naming some other
region is still a miss and does not resolve to a same-named dashboard here.
What Floci mints is not changed. Clients may already hold the ARNs it has handed
out, so bringing the minted shape into line with AWS alters values already in
circulation and belongs in its own change; it is tracked separately. The tolerant
lookup is all that is needed to keep this path correct, and it is strictly more
permissive than before, so it cannot break a caller that works today.
Alarms and metric streams were checked rather than assumed: both mint region-ful
ARNs and AWS documents both region-ful, so the question is dashboards only.
Also reworded the not-found message on the alarm path to name the ARN that did not
resolve instead of asserting it was an alarm. Both tag handlers route every ARN that
is not a dashboard and not a metric stream to that path, including kinds AWS
considers taggable and Floci does not serve, a Contributor Insights insight-rule ARN
being the one AWS documents. Reporting that no resource matches the ARN is true of
those; "alarm not found" was not. No Contributor Insights support is added here.
* test(cloudwatch): assert a refused tag call left the real resource untagged
The not-found tests tagged the unknown ARN env=prod and then re-tagged the real
resource env=dev before reading it back, so a failed call that had written through
to the real resource would have been overwritten and the assertion would still
pass. Read the real resource's tags first; they must be empty.
* test(cloudwatch): import matchers and use configureAwsContentTypes
Import Matchers.not and java.util.Map in the new tests instead of writing
them inline, register the x-amz-json content types through
RestAssuredJsonUtils.configureAwsContentTypes() in place of registerParser
and the hand-built encoder config, and drop DeleteDashboards from the
requireDashboard Javadoc: only GetDashboard declares ResourceNotFound.
(cherry picked from commit 0c8d1848541392ff91991121d96586db564cb3f8)
RevokedTokenInfo serialized its derived isExpired() as "expired", which the
persistent store's ObjectMapper then refused to read back. On restart the file
was moved aside as .corrupt and every revocation was forgotten, so refresh
tokens revoked by sign-out worked again. The derived field is no longer
written, and files that carry it are read with it ignored.
The streaming change from upstream (#5278) serves S3 origins through
S3Service.openObject, which upstream added in a larger disk-streaming rework
(#4691) not taken here. This adds the same method on top of the existing
openObjectStream.
Closes#5425
Adapted: kept only the runtime check; the duplicate-name check that surrounds it
upstream comes from a later CloudFront Functions change not taken here.
(cherry picked from commit 8deac0a4244449470d6bd4bfa8769f8921d1533d)
A distribution read every origin response whole before answering the
viewer: an S3 origin's object through getObject, a custom origin's body
through the HTTP client into a byte array. A viewer's POST, PUT, PATCH
or DELETE body was likewise read whole before it was forwarded. So an
object or upload of about 2 GiB or more failed, and a smaller one could
run the heap out of memory.
S3 origins now open the object as a stream, the snapshot GetObject
serves, and custom origins return their response before its body is
read; either body is written to the viewer as it arrives, with its
Content-Length, or chunked as the origin sent it. A viewer's body is
streamed to the custom origin with its Content-Length, or chunked when
the viewer sent it chunked or, as HTTP/2 allows, with no length.
An origin response closed before its end, as when the viewer goes away
or a custom error page replaces it, cancels its request instead of
reading the rest of the body to reuse the connection. Since a streamed
response holds its connection for the whole transfer, one origin may
now use the whole connection pool, as CloudFront sets no per-origin
limit.
(cherry picked from commit 1f1d4f94dd8a179972bda124bc3aa47b9704f69b)
Custom origins only ever received the origin custom headers: the serving
controller built each origin request from them alone and dropped the
query string, whatever cache policy, origin request policy or legacy
ForwardedValues the matched cache behavior carried.
CloudFrontOriginRequestBuilder now decides what reaches the origin. With
a cache policy it forwards the union of the cache policy's
ParametersInCacheKeyAndForwardedToOrigin and the origin request policy
(every HeaderBehavior, CookieBehavior and QueryStringBehavior value).
Without one it applies legacy ForwardedValues, including the headers
CloudFront forwards by default. It also adds what CloudFront always
sends: Host for the origin unless the viewer Host is forwarded,
User-Agent "Amazon CloudFront", X-Forwarded-For, Via and X-Amz-Cf-Id.
Authorization is kept on the methods CloudFront does not cache, and
CloudFront-Forwarded-Proto, -Viewer-Address and -Viewer-Http-Version are
generated when a policy asks for them. Origin custom headers now replace
every same-named viewer header, and signing parameters are still never
forwarded.
The eight AWS managed origin request policies are served by their AWS
IDs and cannot be updated or deleted. With no origin request policy and
nothing selected by the cache policy, no cookies or query strings are
forwarded, as before.
Closes#4217
(cherry picked from commit f8f1b56ce9e9a1cbd63642ec1c4144fe8f6dd661)
The serving controller only declared GET, HEAD and OPTIONS, so a write
method on a distribution host matched the resource class but no method
and fell through to a bare 405, even when the cache behavior allowed all
seven methods.
POST, PUT, PATCH and DELETE are now served under the same AllowedMethods
check (403 "Invalid method." otherwise) and the same trusted key group
enforcement as the read methods. Custom origins receive the method, the
viewer request body, its Content-Type and its Authorization header, with
Content-Length taken from the body; GET and HEAD still reach the origin
without Authorization, as on CloudFront. In-process S3 origins answer
these methods with 403 Access Denied instead of forwarding them, which
is documented.
Closes#4216
(cherry picked from commit 4ca0e085cd9064cf7672cb050049e9564b48ed55)
The hosted login page now offers a "Continue with <provider>" button for each
of the app client's other SupportedIdentityProviders, carrying the same
authorize parameters (state, nonce, PKCE) into the federated flow, as Cognito's
managed login does. A client that lists only external providers gets the
buttons without the password form instead of an error.
The pool's own users can now sign in through /oauth2/authorize the way apps
expect Cognito to work: without identity_provider (or with COGNITO) the
browser lands on a hosted login page, and a correct password redirects to the
registered callback with a one-time code.
- GET/POST /cognito-idp/login (and /login on custom domains), with a CSRF
cookie and the same password rules and Pre/Post Authentication triggers as
USER_PASSWORD_AUTH; wrong passwords, unknown and unconfirmed users get the
same answer until the password is right
- a one-hour browser session, so the next authorize skips the form unless it
sends prompt=login, and /logout with LogoutURLs validation
- PKCE S256 on both hosted and federated codes, and nonce in the ID token
- refresh_token grant on /oauth2/token
- codes now fire Pre Token Generation with TokenGeneration_HostedAuth instead
of skipping the trigger
Spawned containers (Lambda, RDS, EKS, EC2, ...) join services.docker-network,
but the address they were given to reach Floci was its IP on the first
user-defined network it is attached to. Once Floci is also attached to an
emulated VPC network, that address is unreachable and every Lambda times out
with "Failed to get next invocation". Prefer the configured network when
Floci is attached to it.