Closed jimfox closed 4 years ago
There are a number of client/service interactions where this would be a good choice. In particular this fits when the security requirements can be met by mutual authentication of client and server.
I vote for this, we have some real world use cases where we would like to use something like this. Also, this feature has already been proposed but than somehow got ignored: https://github.com/OAI/OpenAPI-Specification/issues/451#issuecomment-135856998
One thing though that from my point of view requires consideration: When I talk about "client certificate authentication" I typically mean a client presenting a certificate during the TLS handshake and the server granting or denying access based on that (as in rfc5264#section-7.4.6) This is not part of any HTTP interaction at all, it's actually one OSI-Layer lower. There is now two points of view that you could take:
I personally take the realist's view.
Still, it will be somewhat hard to cramp a TLS based client certificate authentication into the existing Security Scheme Object - this one is heavily based on HTTP. Smartest solution I see for now is adding another type and making all the other fields optional for it.
As for the name of this new type I am not really sure what is the standard name for client certificates in the TLS handshake, I have read mTLS (for mutual TLS) in some contexts, but never really in RFCs. Also, the term mutual makes it somewhat confusable with mutual HTTP authentication - a whole different story. I therefore propose to simply name the type tls
- the authentication is based on TLS.
Users might then want to use the description to state the requirements for the cert, but this is optional as servers typically send a list of accepted CAs during the handshake (rfc5246#section-7.4.4).
A typical client certificate security definition would therefore then look like this:
{
"type": "tls",
"description": "Cert must be signed by evilcorp.com CA"
}
type: tls
description: Cert must be signed by evilcorp.com CA
Concur. I have a number of customers who require TLS with client certificates. If we don't add it to OpenAPI I'll have to write an extension. Better to have it as part of the spec.
@cmheazel thanks for the additional data-point. As per #1466 this request is under consideration for OAS 3.1
Within the Dutch public sector we have identified this requirement as well. b.t.w. @cmheazel nice to see you here as well ;)
We also plan to implement a REST API service for EU Customs & Taxations IAM system between European Commision and member states. In that case, it is far more easier for us to use two-way SSL as it is already the case for the SOAP WS already exposed. But for the moment my major problem is the lack of implementation at server-side. I had to switch back to Swager 2.0 api because of that. I hope that a 3.0 implementation will come soon, but I have doubt that the 3.1 will met my dead lines. Do we have an idea when 3.1 specifications will be frozen?
@tobilarscheid I support your realist view. The Dutch municipalities are aiming to convert/replace their current monolithic information systems with an API-first software landscape, fulfilling societal demand for automation, transparency and privacy. To facilitate this we are setting up an open source inter-organisational system facilitating federated authentication, secure connecting and protocolling in a large-scale, dynamic API landscape. In this landscape we want to use two-way TLS.
On the subject of TLS client certificate authentication, as a straw man, would the following be sufficient to indicate that the client MUST provide a TLS certificate?
components:
securitySchemes:
clientCert:
type: clientTLS
serverSelfSigned: true
The default value of serverSelfSigned
would be false
. A true
value would indicate that the client MUST accept self-signed certificates from the server.
Client-side tools would be free to identify or prompt for the relevant certificate using any means they wish.
Hi @MikeRalphson, thanks for your input. The solution looks like a good first step to me. However I do not quiet understand the emphasis on serverSelfSigned
- why would that be something so important to include it here right away?
Hello,
I agree. Moreover, self-signed certificates are not used in production environements.
If you want to put more information useful for the client side, you could optionally list the CA certificates or URL of CA or eIDAS / alternate LOTL (for European Union) that are trusted for an 2 WAY SSL authentification with this service. But it should only be informative.
Pascal
On 15 May 2018 at 09:55, tobilarscheid notifications@github.com wrote:
Hi @MikeRalphson https://github.com/MikeRalphson, thanks for your input. The solution looks like a good first step to me. However I do not quiet understand the emphasis on serverSelfSigned - why would that be something so important to include it here right away?
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/OAI/OpenAPI-Specification/issues/1004#issuecomment-389077541, or mute the thread https://github.com/notifications/unsubscribe-auth/AiSLQN7RoFEVJbRJioNpVCP_r5vMt_-_ks5tyonbgaJpZM4MmFhZ .
@tobilarscheid @bourgpa re: self-signed certificates, this is completely up for debate, and is potentially an unwanted feature / in the wrong place, but I wanted to bring up the subject.
Moreover, self-signed certificates are not used in production environements.
This, unfortunately. is not the case in my experience. When an organisation manages their own CA, they sometimes issue self-signed certificates both for servers and clients. They may also have a place in microservice environments.
Personally, my feeling is that we should not list CAs, root certificates, CNs, or tread on the toes of TLS's negotiation of ciphers etc by including this information, but we are open to all use-cases and perspectives regarding this feature.
When an organisation manages their own CA, they sometimes issue self-signed certificates both for servers and clients. They may also have a place in microservice environments.
It really does not matter for security who signed the certificate as long as you trust the signee - on the other hand accepting a certificate that is signed by someone you don't trust / know is typically a bad idea. Because of this I deem the flag unnecessary / even misleading.
Personally, my feeling is that we should not list CAs, root certificates, CNs, or tread on the toes of TLS's negotiation of ciphers etc by including this information, but we are open to all use-cases and perspectives regarding this feature.
You are right that this is part of the TLS handshake already. Might still be nice to include just for informational purpose, but that could be something that can live in a comment field or the like as well IMHO.
@tobilarscheid
It really does not matter for security who signed the certificate as long as you trust the signee - on the other hand accepting a certificate that is signed by someone you don't trust / know is typically a bad idea. Because of this I deem the flag unnecessary / even misleading.
It may matter to the client's authentication libraries, which often must be passed a flag to disable the checking for self-signed certificates.
You are right that this is part of the TLS handshake already. Might still be nice to include just for informational purpose, but that could be something that can live in a comment field or the like as well IMHO.
Indeed, specification extensions / the new draft features approach may be a way to make this extensible.
It may matter to the client's authentication libraries, which often must be passed a flag to disable the checking for self-signed certificates.
that's what I say you should never do and specifically should not be promoted by this standard here.
that's what I say you should never do and specifically should not be promoted by this standard here.
I understand your concern, but allowing the description of a particular API implementation is not necessarily promoting it. cf. cookie
parameters. The OAS is a specification for describing APIs, not a standard or a set of best-practices. My intention in including it was so this issue got debated.
We may be making this harder than it has to be.
TLS runs below HTTP on the protocol stack. The scope of an OpenAPI document, and the software processing it, is not likely to extend to that level. So anything the OAS document has to say about TLS client certificates is informative. A Security Requirement Object of:
{
"authentication:ietf:5246:client_certificate": []
}
may be sufficient.
The only impact this will have on the OAS specification is that we would have to:
a) allow Security Requirements that do not map to a Security Schem or
b) allow more values in the type field of the Security Scheme objects or
c) both a and b.
Option B may also be useful for implementing the cryptographic extension discussed a couple weeks ago.
@cmheazel If docs tools are going to implement "try it" functionality against servers that are in a dev environment where certs are self-signed, they are going to need to know to turn off any cert validation.
@cmheazel
b) allow more values in the type field of the Security Scheme objects or
As above, this is the option we're discussing.
Sorry, I miss-read the example. This relates to issue #1552
@darrelmiller But is that in-scope for OAS? In my experience, client side certificates are configured once and never modified. Any changes required for a dev environment are passed out of band.
@bourgpa I have similar requirements too (always for public administrations).
@MikeRalphson what do you think of using the more general x509 reference?
components:
securitySchemes:
clientCert:
type: x509
@ioggstream fair question. All TLS communication uses x509 certificates, but we probably want to make it clear that for this type
of securityScheme
the client must additionally present a certificate (in the above example clientCert
is an arbitrary identifier, and could be anything). Perhaps to disambiguate any future client certificate types and to indicate the x509 certificate should have the Client Authentication extended key usage, we could use x509client
or similar?
Perhaps we should introduce security scheme types for both TLS and TLS_Mutual_Authentication. This makes it clear that the client certificate is being used within the context of the TLS protocol. This is probably a good time to dust off the crypto extension proposal.
Perhaps we should introduce security scheme types for both TLS and TLS_Mutual_Authentication
How does this square with your earlier comment
TLS runs below HTTP on the protocol stack. The scope of an OpenAPI document, and the software processing it, is not likely to extend to that level. So anything the OAS document has to say about TLS ... is informative
? TLS usage is a function of the server
in use for communication and does not directly relate to the OAS concept of security.
This is probably a good time to dust off the crypto extension proposal.
Not directly in this issue, I feel. That is a much bigger change and focuses on one particular approach to crypto. I expect @isamauny and other interested parties to comment here if this particular proposal conflicts with the crypto extension proposal.
@MikeRalphson I made my point. Since the consensus seems to be that TLS-level security is in scope for OAS, we move on. What I'm trying to avoid here is a point solution. If we are going to support one optional TLS capability, then we should do it in a way that is extensible.
@MikeRalphson I agree that crypto is a separate issue. But it is related and should be coordinated.
Hi @MikeRalphson, and thanks for your time!
we probably want to make it clear that for this type of securityScheme the client must additionally present a certificate [...] with the Client Authentication extended key usage Fair. The goal is to support future definitions based on x509 (eg. SSL -> TLS -> ULS -> WLS ;) )
components:
securitySchemes:
clientCert:
type: x509client
@simo5 could it be ok for that case? https://github.com/openshift/origin/pull/14745#discussion-diff-123263482R683
@darrelmiller not sure that we can manage to always tryit
with mutal-tls. The server should be willing to accept an untrusted cert too. We could just provide something in the swagger-ui for that, but not in the spec.
@ioggstream our intent is to only convey what authentications schemes are accepted, and mTLS is one of them. Note that a server will never accept an untrusted cert, but also that you do not have to use a client cert, mTLS can be optional, if you come with a cert you are implicitly authenticated (or not, depending on configuration) at the HTTP layer, if you come without a cert then you are just anonymous.
@simo5 thx for your reply!
our intent is to only convey what authentications schemes are accepted, and mTLS is one of them.
Sure: do you think the above spec proposal x509client
will cover your use case?
Note that a server will never accept an untrusted cert
Sure: that's why I said that the specs shouldn't tell anything on trust (see https://github.com/OAI/OpenAPI-Specification/issues/1004#issuecomment-389184421)
mTLS can be optional, [..] if you come without a cert then you are just anonymous.
afaik OpenAPI allows multiple securitySchemes
, eg
components:
securitySchemes:
clientCert:
type: x509client
BasicAuth:
type: http
scheme: basic
@MikeRalphson iiuc https://github.com/OAI/OpenAPI-Specification/issues/14#issuecomment-297457320 says the following, right?
paths:
/ping:
get:
summary: Checks if the server is running
# Both unauthenticated and x509client
security:
-
- x509client
...
how do you specify a path with both anonymous and clientCert?
The syntax is non-obvious (and we have previously solicited PRs to make it clearer / provide an example in spec), but providing optional security requirements is explained in this comment (which it has taken me :rage: amount of time to locate):
https://github.com/OAI/OpenAPI-Specification/issues/14#issuecomment-297457320
@simo5 : some servers will definitely accept untrusted certificates (ssl_verify_client optional_no_ca in NGINX conf or SSLVerifyClient optional_no_ca in Apache conf, for example). It means that you don't want to use TLS for Authentication but only for integrity and confidentiality of exchanged messages. There are a few use-cases for that, specially when you already convey Authentication information using another mechanism.
It could be nice to add two Security Scheme Object types, x509client to require client certificate based mTLS AuthN and none, to solve elegantly the "both anonymous and clientCert" problem.
@pleothaud
It could be nice to add [...]
none
, to solve elegantly the "both anonymous and clientCert" problem.
none
would just be another way of writing
security:
- {}
and though it may be clearer, the OAS currently favours a more Pythonic ("There should be one - and preferably only one - obvious way to do it")* approach rather than a Perl-style TMTOWTDI approach.
* For some value of "obvious".
@pleothaud from the POV of the securityScheme, that is equivalent to not specifying x509client at all. We care for exposing a x509 Certificate label only if the client can use a cert to authenticate.
@simo5 from the POV of securityScheme (and hence AuthN) you're right, but for the POV of the ability to consume the API you have to express that the client will have to provide a client certificate to be able to connect.
This is why in addition to the AuthN related requirements (expressed in the Security Scheme, Security Requirement objects and finally in the security fixed field of the Operation object), we should be able to express constraints at the Server object level.
These constraints should express at least:
If a client certificate is required or accepted we should have in addition:
WDYT?
Such an extension to the Server object plus the addition of a x509client Security Scheme Object types would allow to express all combinations of mTLS optional or required, as well as mixing operations requiring no authentication, some other requiring Basic or OAuth only and others requiring mTLS (potentially in addition to Basic or OAuth)
If clientCertificateRequired is required, the Security Requirement stating that an x509client Security Scheme is required to consume a specific Operation will be redundant information (as mTLS AuthN is in this case sort of a side effect of Transport level TLS configuration) but it will anyway be more readable for developers, IMHO
@MikeRalphson I'd never dare to say that Perl is more elegant than Python ;-)
@pleothaud I do not think it makes sense to notify whether the server certificate is self-signed or not. Either the client trusts it or it doesn't, the server doesn't get to tell the client "I am self signed TRUST me".
Servers need to accept connections w/o client certificates (otherwise you can't even get the OpenAPI definitions without prior knowledge). I am not sure that it makes any sense to advertize the server accepts self-signed but untrusted client certs, it has no purpose.
If the server advertizes that it accepts x509client authentication, then a client can try to use the certs it has, if all of them fail it can try to fallback to non cert based auth. The client can autodetect if a server accepts untrusted certificates [because the connection will go through the TLS layer but requests will fail as unauthenticated as opposed to fail at the TLS connection layer], so the client can decide whether it wants to use a client cert or not; from the POV of a server it makes no sense to require an untrusted client cert as it provides no additional security.
So I am definitely against codifying any option that hints at accepting untrusted certificates, as it is useless from a security POV and/or can be simply probed by the client.
@simo5
2.a. OAS files can be retrieved by other means than an HTTP(S) request 2.b. OAS files can be retrieved for instance from an API developer portal (or any other kind of repo) and then do not have to be retrieved on the backend server exposing directly the API
I'm not sure your assertion that an API backend cannot require a client certificate at TLS level for the whole server can be accepted in any high security environment.
I personnally don't like neither the use of untrusted certificates but in the end it exists, for some good or bad reasons... As they say, "be liberal in what you accept" otherwise you block adoption.
@pleothaud I understand the use case for (1), but it is simply misguided.
A client can never trust a server to tell it to lower all security, otherwise that client is broken by definition (as it can be told the same when in production). Therefore advertizing anything of the sort is simply useless, the developer still need to actively tell the client it is ok to trust an untrusted server. It is therefore something that a server has no reason to advertize to start with.
ok on (2).
On (3) please do not mix TLS with PKI and/or x509 certs, these 3 technologies are inter-related but not mutually interchangeable concepts.
In that oauth drafta a very contrived method is used to postpone validation of certificates to the application layer. But this simply means that the server is not doing mTLS, it is just accepting connnections where clients happen to present an untrusted client certificate and then the server also allows the application to request data on that certificate. This kind of authentication need to be advertized in a different way via a specific oauth+x509cert label or similar, it has nothing to do with regular x509client and should not be mixed in here.
The point is, you can use untrusted certificates, but it makes no sense for a server to advertize it explicitly, because there is nothing the client can do and nothing the client should do. Either the client has certs to use or it doesn't, either the client trusts the server cert or it doesn't, nothing the server will say about the trustworthiness of certs matters.
@pleothaud imho
components:
securitySchemes:
clientCert:
type: x509client
subjectAltName:
- DNS
@MikeRalphson @simo5 if we all agree at least on this model we could make an RFE and push for that.
components:
securitySchemes:
clientCert:
type: x509client
# We are still free to add stuff here.
BasicAuth:
type: http
scheme: basic
paths:
/ping:
get:
summary: Both unauthenticated and x509client
security:
- {}
- clientCert: []
...
post:
summary: >-
Only with x509client. The server (un)trust configuration shouldn't be in the contract as it may
vary between different environments. The API shouldn't vary b/w dev/test/prod.
security:
- clientCert: []
@ioggstream sounds reasonable to me
@ioggstream I think your example should have said...
security:
- {}
- clientCert
Security Requirement objects reference the key of the security scheme.
@darrelmiller thx++ Fixed (see above).
Final sanity check, is the security scheme type sufficiently unambiguous? 1) Might there be a case where we are using X.509 client certs but not over TLS? 2) Might there be a case where the TLS client cert is not X.509? 3) Is there a case where a client certificate is used that is neither TLS nor X.509? 4) Are there other variants we may have missed? Keep in mind that we are still running code written 30 years ago. Plan for the future.
I guess you could call it TLSClientCertificate, and avoid all of the above questions.
@cmheazel imho:
SSL
Nothing you can't specify in scheme
;)
ULS
;) ) means a rename. I'd rather use a scheme
. securitySchemes:
clientCert:
type: x509client
spec: tls # or rfc5246|mtls|whatever
@ioggstream You win the prize.
Thank you everyone for the comments - I'm still going through them. I hope to be able to summarise where we're at in time for the next TSC meeting on June 4th.
Just a note @darrelmiller and @ioggstream :
security:
-
does not mean the same as
security:
- {}
An empty definition in YAML is shorthand for null
, not the empty object, as is required to indicate a none
security requirement.
Final sanity check, is the security scheme type sufficiently unambiguous?
@cmheazel The unambiguity will be addressed by the spec. defining its terms (i.e. what it means by tlsClientCert
or whatever type value we agree on). What we're primarily seeking is clarity.
@ioggstream: scheme
is a term with a defined meaning in RFC7235 - which effectively defines a subtype of http
authentication, 'Scheme' in TLS seems generally to be used with regard to "signature schemes". Even if we are defining a subtype here I think we should avoid the term 'scheme'. If we are in fact defining a supertype, then we probably have our type value wrong.
Use of client certificate for authn is very popular and support is ubiquitous.