Skip to content

[Mailer] added Instance Profile support to SES Transport of Mailer #33326

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

connorhu
Copy link
Contributor

@connorhu connorhu commented Aug 25, 2019

Q A
Branch? 5.0
Bug fix? no
New feature? yes
BC breaks? yes
Deprecations? no
Tests pass? yes
Fixed tickets #33183
License MIT
Doc PR -

This PR adds Instance Profile support to SES API and Http Transport of Mailer component.

Things to do:

  • changelog. I'm not sure about the version of the changelog entry, maybe 4.4.0.

The token expiry is an unhandled situation. But I'm not sure that the Transport part of the Mailer component can support transport renew.

Copy link
Member

@fabpot fabpot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! Can you also add a note in the CHANGELOG of the component about the BC break?


$instanceMetadataServerURL = $this->getInstanceMetadataServerURL($roleName);

while (true) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we try several times?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The amazon sdk does the same. I guess connecting to the 169.254.169.254 IP sometime may temporary fail, so thats why I did keep the same logic.

@OskarStark
Copy link
Contributor

This feature must target 4.4 branch please

@fabpot
Copy link
Member

fabpot commented Aug 26, 2019

@connorhu As noticed by fabbot, you should rebase to get rid of the merge commits. And you should rebase on 4.4 instead of master. The current situation is a bit special as we are working on 2 versions in parallel: 4.4 and 5.0/master.

}

if ('smtp' === $scheme || 'smtps' === $scheme) {
return new SesSmtpTransport($user, $password, $region, $this->dispatcher, $this->logger);
return new SesSmtpTransport($credential, $region, $this->dispatcher, $this->logger);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if an ApiTokenCredential was instantiated and we reach this point ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stof I think the supported credential type(s) should be checked by the Transport instance.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stof SesSmtpTransport only works with UsernamePasswordCredential (as you can see at the first parameter of the constructor). DX would be better if we check the class and throw an exception with a better message than a native type exception.

@connorhu
Copy link
Contributor Author

@fabpot Ok. When I started to work on this I didn't know the right branch because of the complexity of the work (eg BC BREAK)

@fabpot
Copy link
Member

fabpot commented Aug 26, 2019

We can break BC here as the component was marked as experimental in 4.3. That eases things a lot :)

@nicolas-grekas nicolas-grekas added this to the next milestone Aug 26, 2019
@nicolas-grekas
Copy link
Member

(this should target branch 4.4)

@connorhu connorhu changed the base branch from master to 4.4 August 26, 2019 13:36
@connorhu connorhu changed the base branch from 4.4 to master August 26, 2019 13:37

$this->client = HttpClient::create();
} else {
$this->client = $client;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking mode on: no need for an else here. Simply do $this->client = $client above where you assign retries. Then check if $this->client is null instead of $client and you can remove the if.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mdeboer I can remove the else, but you're right.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry yeah, I meant the else hehe 😜 Blame the heatwave..

@connorhu connorhu changed the title added Instance Profile support to SES Transport of Mailer [Mailer] added Instance Profile support to SES Transport of Mailer Aug 29, 2019
@fabpot fabpot added the Mailer label Sep 2, 2019
@fabpot
Copy link
Member

fabpot commented Sep 2, 2019

@connorhu I'm going to rebase on 4.4 this PR.

@fabpot
Copy link
Member

fabpot commented Sep 2, 2019

@connorhu It's a bit more difficult than expected due to the recent changes in the code. Can you have a look? I think the SesRequest class is not the right abstraction. Tell me if you need help.

@connorhu
Copy link
Contributor Author

connorhu commented Sep 2, 2019

@fabpot What would be the right abstraction instead of SesRequest? We need to create a bunch of headers from the content and it needs to be a reusable logic because of SesApiTransport and SesHttpTransport. Both of them use this code, but both use a slightly different way.

@fabpot
Copy link
Member

fabpot commented Sep 4, 2019

@connorhu Not sure yet. I let you rebase and I think you will understand what I mean. Some logic in SesRequest are needed in __toString() as well.

@connorhu
Copy link
Contributor Author

connorhu commented Sep 4, 2019

@fabpot Ok then. I will do the rebase.

Copy link
Member

@jderusse jderusse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AWS SDK provides many way to authenticate (some of theme are really simple), What's about implementing the most used and chaining theme (in the same way SDK does) ?

I think about AWS config File, official AWS_ENV vars and "assumed role with web identity" (the last one is used when using EKS(K8S) and allocating a ROLE to a ServiceAccount)

$credentialProvider = new ChainCredentialProvider([
  new UserPassProvider($user, $password),
  new EnvVarProvider(),
  new ConfigFileProvider(),
  new RoleProvider(),
  new OidcProvider(),
]);

throw new LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__));
}

$this->client = HttpClient::create();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the default timeout is 1.0s in official SDK

} catch (IncompleteDsnException $e) {
$role = $dsn->getOption('role');

if (null === $role) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

role is not needed. In official AWS SDK, the role is fetched from instance metadata. (see InstanceProfileProvider)

@fabpot
Copy link
Member

fabpot commented May 3, 2020

Closing in favor of #35992

@fabpot fabpot closed this May 3, 2020
fabpot added a commit that referenced this pull request May 3, 2020
This PR was squashed before being merged into the 5.1-dev branch.

Discussion
----------

[Mailer] Use AsyncAws to handle SES requests

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | #33183, #35468 and #35037
| License       | MIT
| Doc PR        | TODO

alternative to #33326

This PR replace the native code to call AWS SES by the new [AsyncAws](https://github.com/async-aws/aws) project maintained by @Nyholm and me.

This removes complexity of signing request, and adds new features likes:
- authentication via .aws/config.ini, Instance profile, WebIdentity (K8S service account)
- usesignature V4 (the one recommanded by the Official SDK )
- fully compatible with API (uses the official AWS SDK interface contract to generate classes)

Because it's based on `symfony/http-client`, it's fully integrable with Symfony application.

Commits
-------

2124387 [Mailer] Use AsyncAws to handle SES requests
@nicolas-grekas nicolas-grekas modified the milestones: next, 5.1 May 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants