Amazon S3 migrating service certificates to Amazon Trust Services - amazon-web-services

I have websites that link directly to images stores on S3 using HTTPS.
For example:
<img src="https://s3.amazonaws.com/MyBucket/FolderInBucket/ImageFileName.png" />
I wanted to know if I need to change anything so my images on my website will still be accessible after the migration.
Source information link.

You won't have to do anything on your end, the certificate swap is handled by AWS. Whether this has an impact on your application depends on your clients, because this change relates to how they do the certificate verification.
The process is roughly like this:
The client makes a request to S3, asking for encrypted communication
S3 sends back a certificate, that contains the public key for the initial key exchange using asymmetric encryption.
The client verifies the digital signature of the certificate, that means:
The certificate is cryptographically signed by a certificate authority (there are intermediate certificate authorities that form a chain of trust, but we're going to ignore these for simplicity.)
This signature means the certificate authority guarantees this certificate to be valid
The signature is trusted, if the certificate authority is trusted. Each client has a list of trusted root certificates in a local trust store, which the client trusts to guarantee the authenticity of certificates
If the new CA is in the local trust store everything is fine, if it isn't there will be an error
Afterwards the client will check, if the certificate in question has been revoked. If yes, the connection is terminated, if not it trusts the certificate and the included public key
The client generates a session key and encrypts it with the public key from the certificate.
The encrypted session key is sent to the server and the server can decrypt it using its private key
Now both partners have the session key and can exchange symmetrically encrypted messages using that session key.
So the main question is: Do your clients have the new CA in their trust store?
The answer is: most likely yes
You can have your clients test this by accessing the URL in the post you linked to, which already uses the new certificate:
https://s3-ats-migration-test.s3.eu-west-3.amazonaws.com/test.jpg
If they see this picture, everything is fine:
You can also do this in the background on your website and check if HTTP 200 is returned when requesting the URL. If that's not the case, inform the client there may be problems in the future.

Related

AWS API Gateway gives 'More than one client certificate passed' error

I have set up Mutual TLS authentication for my API Gateway.
I then placed my client certificate in the truststore. The file contains the client certificate, intermediate and root certificates (private CA).
When accessing the API Gateway with a browser (Chrome on Windows), browser asks me to provide client certificate. I select the same certificate as I have placed in the trust store.
API Gateway reports the following in the browser:
{"message":"Invalid client certificate chain. More than one client certificate passed"}
UPDATE: I have also tried placing only intermediate and root certs in the trust store. Same error.
UPDATE 2: The same error is also reported when accessing the API with C# code (WebClient) loading the cert from Windows cert store or from disc (pfx file).
If your trust store doesn't contain all the intermediate CA certs, then the client has to send a multi-cert chain. The TLS handshake will work fine, but somewhere there is an explicit check that disallows multi-cert chains. The status code is 400, not 403(!), and you get the "More than one client certificate passed" error.
However, if you're willing to put all the intermediate CA in the API gateway trust store, then the server should not ask the client to send intermediate certs. The client should only send one cert in this case, and API gateway should work.
So something is going wrong when API gateway matches the initial client cert against the trust store, and it's not finding the intermediate. I would check these things:
Make sure you use a specific version ID with the S3 link to the trust store. Otherwise it's hard to tell which version it's actually using, because the API gateway will not automatically pick up a new version as soon as you add one to S3. Maybe you're not using the trust store you think you are.
Your trust store should only include CA certs -- the root cert and intermediates. You said you put the client cert in there, so maybe that's causing an issue. Try taking it out.

Tomcat - WebService - without Trust Store

We have a Webservice Application running on Tomcat.
This is SSL secured. We need to share our public key to every client trying to access our web services. Is it possible to disable the trust certificate verification ?
By default, all TLS clients should verify the servers to which they are connecting. Any other default behavior would be dangerous.
The client is the party performing the verification in a one-way TLS handshake (that is, when there is no client-authentication being performed where the client also presents a certificate to the server).
There are only two ways to avoid distributing your server's certificate to all possible clients:
Get your server's certificate signed by a trusted Certificate Authority (CA)
Modify all possible clients to ignore any problems with your certificate (such as not trusting it)
These days, with free domain certificates available from e.g. Let's Encrypt, it's silly not to use a certificate signed by a legitimate CA.

Haproxy to authorize traffic from AWS API Gateway

I have set up a basic API using AWS API Gateway and I would like to link my endpoints to a service I have running on an EC2 instance (using the "HTTP Proxy" integration type). I have read that in order to lock down my EC2 server from only accepting traffic from the API Gateway, I basically have one of two options:
Stick the EC2 instance behind VPC and use Lambda functions (instead of HTTP proxy) that have VPC permissions to act as a "pass through" for the API requests
Create a Client Certificate within API Gateway, make my backend requests using that cert, and verify the cert on the EC2 instance.
I would like to employ a variation of #2 and instead of verifying the cert on the EC2 service instance itself, I would like to instead do that verification on another instance running Haproxy. I have set up a second EC2 instance with Haproxy and have that pointed at my other instance as the backend. I have locked down my service instance so it will only take requests from the Haproxy instance. That is all working. What I have been struggling to figure out is how to verify the AWS Gateway Client Certificate (that I have generated) on the Haproxy machine. I have done tons of googling and there is surprisingly zero information on how to do this exact thing. A couple questions:
Everything I have read seems to suggest that I need to generate SSL server certs on my Haproxy machine and use those in the config. Do I have to do this, or can I verify the AWS client cert without generating any additional certs?
The reading I have done suggests I would need to generate a CA and then use that CA to generate both the server and client certs. If I do in fact need to generate server certs (on the Haproxy machine), how can I generate them if I don't have access to the CA that amazon used to create the gateway client cert? I only have access to the client cert itself, from what I can tell.
Any help here?
SOLUTION UPDATE
First, I had to upgrade my version of HAproxy to v1.5.14 so I could get the SSL capabilities
I originally attempted to generate an official cert with letsencrypt. While I was able to get the API gateway working with this cert, I was not able to generate a letsencrypt cert on the HAproxy machine that the API gateway would accept. The issue surfaced as an "Internal server error" response from the API gateway and as "General SSLEngine problem" in the detailed CloudWatch logs.
I then purchased a wildcard certificate from Gandi, and tried this on the HAproxy machine, but initially ran into the exact same problem. However, I was able to determine that the structure of my SSL cert was not what the API gateway wanted. I googled and found the Gandi chain here:
https://www.gandi.net/static/CAs/GandiStandardSSLCA2.pem
Then I structured my SSL file as follows:
-----BEGIN PRIVATE KEY-----
# private key I generated locally...
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
# cert from gandi...
-----END CERTIFICATE-----
# two certs from file in the above link
I saved out this new PEM file (as haproxy.pem) and used it in my HAproxy frontend bind statement, like so:
bind :443 ssl crt haproxy.pem verify required ca-file api-gw-cert.pem
The api-gw-cert.pem in the above bind statement is a file that contains a client cert that I generated in the API gateway console. Now, the HAproxy machine properly blocks any traffic coming from anywhere but the gateway.
The reading I have done suggests I would need to generate a CA and then use that CA to generate both the server and client certs.
That's one way to do it, but it is not applicable in this case.
Your HAProxy needs to be configured with a working SSL certificate signed by a trusted CA -- not the one that signed the client certificate, and not one you create. It needs to be a certificate signed by a public, trusted CA whose root certificates are in the trust store of the back-end systems at API Gateway... which should be essentially the same as what your web browser trusts, but may be a subset.
Just as your web browser will not speak SSL to a server sporting a self-signed certificate without throwing a warning that you have to bypass, the back-end of API Gateway won't negotiate with an untrusted certificate (and there's no bypass).
Suffice it to say, you need to get API Gateway talking to your HAProxy over TLS before trying to get it to use a client cert, because otherwise you are introducing too many unknowns. Note also that you can't use an Amazon Certificate Manager cert for this, because those certs only work with CloudFront and ELB, neither of which will support client certs directly.
Once the HAProxy is working with API Gateway, you need then to configure it to authenticate the client.
You need ssl and verify required in your bind statement, but you can't verify an SSL client cert without something to verify it against.
I only have access to the client cert itself, from what I can tell.
And that's all you need.
bind ... ssl ... verify required ca-file /etc/haproxy/api-gw-cert.pem.
SSL certs are essentially a trust hierarchy. The trust at the top of the tree is explicit. Normally, the CA is explicitly trusted and anything it has signed is implicitly trusted. The CA "vouches for" the certificates it signs... and for certificates it signs with the CA attribute set, which can also sign certificates under them, extending that implicit trust.
In this case, though, you simply put the client certificate in as the CA file, and then the client certificate "vouches for"... itself. A client presenting the identical certificate is trusted, and anybody else is disconnected. Having just the certificate is not enough for a client to talk to your proxy, of course -- the client also needs the matching private key, which API Gateway has.
So, consider this two separate requirements. Get API Gateway talking to your proxy over TLS first... and after that, authenticating against the client certificate is actually the easier part.
I think you are mixing up server certs and client certs. In this instance API Gateway is the client, and HAProxy is the server. You want HAProxy to verify the client cert sent by API Gateway. API Gateway will generate the certificate for you, you just need to configure HAProxy to verify that certificate is present in every request it processes.
I'm guessing you might be looking at this tutorial where they are telling you to generate the client cert, and then configure HAProxy to verify that cert. The "generate the cert" part of that tutorial can be skipped since API Gateway is generating the cert for you.
You just need to click the "Generate" button in API Gateway, then copy/paste the contents of the certificate it presents you and save that as a .pem file on the HAProxy server. Now I'm not a big HAProxy user, but I think taking the example from that tutorial your HAProxy config would look something like:
bind 192.168.10.1:443 ssl crt ./server.pem verify required

How can I verify a self-signed certificate?

I am currently writing a desktop app which will need to communicate with PHP scripts on my remote server via https(with a self-signed certificate). The server-client communication code is still in the planning stages, however because I haven't yet figured out how to verify (on the client) that I am actually communicating with MY server. I'm presuming that there is some way to verify the servers identity using the certificate. I am intending to use WinHTTP for the https communication, providing it has all of the functionality that I need.
To greatly oversimplify things: clients verify the server's certificate by using a hardcoded list of trusted certificate authorities. The certificate authority list is an internal list of certificates that's baked into the client, and the client verifies that the certificate presented by the server is signed by one of the certificate authorities that the client trusts.
So, no matter what you end up doing, your client will have to keep some kind of a list of certificates that it trusts. This is a fundamental aspect of the TLS trust model. You could simply include your self-signed certificate with the client, and the client verifies that that your server presented the same certificate.
But the right answer is to run your own certificate authority. It involves some additional advance prepwork, but the end result will work much better. Instead of the several dozen, or so, standard certicicate authorities that are either included in your operating system, or your browser, your client will have exactly one trusted certificate authority in its trust list: your own certificate authority, and your client will verify that your server's certificate is signed by your certificate authority.

Using a self signed SSL certificate just for a web service

I have a web service that clients will have and I want the data that's sent to the server encrypted. To test this I used a self signed SSL certificate. I know that when you use a self signed cert and when you navigate to whatever address is using it that the web browser will warn you that it's unsafe etc.
I am wondering if I'm I going to run into any problems if I used this certificate instead of a verified one when the web service goes live?
Also I don't have a domain name for the server, so I am just going to use the IP address given by my ISP, is this ok to do so with the certificate, because everywhere I read about them people are talking about using them with domain names?
An SSL certificate is usually issued to a domain and is signed by an issuing authority. When a browser connects to a server the server presents its certificate to the client. The client then verifies the certificate by checking if the domain that it is accessing is the same one as mentioned in the certificate. Also, it verifies its trust chain. This means that the issuer's certificate should also be valid. If the issuer is not the root signing authority then the issuer's issuer's certificate is verified. And, ultimately the root signing authority should be trusted which means the root signing authority should be in your truststore. All major signing authorities like Verisign, Thawte etc are by default in the JDK trustore hence if you have a certificate signed by them then you do not have issues in the verification of your trust chain. If your certificate is signed by an authority that is not trusted then you need to import the issuer's certificate in your trust chain manually.
Now, when using a self signed certificate, the entity to whom the certificate is issued is itself is the root signing authority. And hence the certificate should be imported into your truststore manually. You need to do this to get your SSL handshake through. But this alone does not solve your problem. Since, you are not using any domain name, your IP is likely to be changed every time you restart your server if you are obtaining your server IP automatically through a DHCP server. If this is the case then even a trusted self signed certificate won't work once the IP changes. Because, the certificate is issued to an IP and once the IP changes the certificate would become invalid. To get around this you need to get a static IP address for your server from your network admin. Then generate a self signed certificate for your static IP. Then ask your clients to add your server certificate in their trust store.
This would be a bit tedious for your clients. But, if you have a fixed number of clients and the client machines are under your control then you could add the server certificate to the client trust store yourself. But, if your server is open to all or have a huge number of client then I would suggest to get a certificate signed by a well known and trusted certification authority. Again, you would still need to have a static IP irrespective of who signs your certificate unless your server gets a domain name.
The issue with self-signed certificates is the same in any scenario, browser or non-browser: it assures absolutely nothing by itself. The purpose of SSL is two-fold: encryption and authentication. Typically both aspects are being used/required by SSL clients for a connection to be really regarded as secure.
For authentication ("who am I talking to?"), certificates are used. To authenticate your peer with a certificate, you will either have to have a copy of that certificate to compare to, or you will need to have a copy of the certificate of a signer of that certificate to compare the signature to. If you have neither, the certificate doesn't assure anything.
Meaning: self-signed certificates are fine if the client has a copy of that certificate and can trust the source of where they got the certificate from. If you have a very narrow use case where every client that's going to connect to your web service will have had prior contact with you (e.g. via email) and you are able to give a copy of the certificate to them for them to install into their local trust store, then they are able to establish a secure and authenticated connection to you regardless.
This is not workable for a typical website with arbitrary, random visitors; that's what signed certificates are for, where an already trusted entity can vouch for a heretofore unknown 3rd entity. It may be workable in a vendor-customer scenario though.
Having said that, certificates are dirt-cheap to free nowadays and lend more credibility and professionalism to your service.
And yes, certificates can be issued for IP addresses.