vespa-engine / vespa

AI + Data, online. https://vespa.ai
https://vespa.ai
Apache License 2.0
5.49k stars 586 forks source link

SSL/TLS configuration support exclusively for configserver #21762

Closed adarshaj closed 2 years ago

adarshaj commented 2 years ago

Is your feature request related to a problem? Please describe. Currently the suggested SSL/TLS setup for configserver is to enable mTLS via specifying VESPA_TLS_CONFIG_FILE env var. An example of this is shown in mTLS reference: https://docs.vespa.ai/en/reference/mtls.html#example

However, this uses the same TLS config for all the components including the internal communications between vespa-nodes. This has a security implication, that any authorized client for any of the component will also be authorized to do configserver changes. For example, the sample example shown above allows monitoring client to also make configserver changes (use deploy API for ex.).

Therefore, I would like to have an option for configuring TLS options exclusively for configserver (somewhat similar to how container server supports TLS via services.xml's http > server > ssl options).

Describe the solution you'd like Since configserver is one of the first component to startup, it cannot have ssl/tls specification in the service.xml, so it must have its own env var equivalent or the file pointed to in VESPA_TLS_CONFIG_FILE should have exclusive options to configure ssl/tls options for configserver.

Describe alternatives you've considered There is no real alternative here other than to use the mTLS which authorizes all the clients for all components the same way.

tokle commented 2 years ago

The mTLS configuration given by VESPA_TLS_CONFIG_FILE will only control which clients are allowed to communicate with the service. It is generally good practice to have separate tls config files for different node types. E.g. for the config server

While the config server does not have the possibility to configure ssl properties using same syntax as a container, it can still be configured. You need to set the configuration in a file http-server.xml in the configserver-app folder. This will be included with: https://github.com/vespa-engine/vespa/blob/73b080b527e303a60a365b2bb95b72dcc2f81f4c/configserver/src/main/resources/configserver-app/services.xml#L150. In this file you can configure your ssl connector for the config server, see jdisc.http.connector.def for reference on what to configure. You would need to set up a server and add the jdisc.http.connector config:

<server port="..." id="...">
    <config name="jdisc.http.connector">
    ...
    </config>
</server>
adarshaj commented 2 years ago

@tokle - That's perfect! I think it will definitely solve my requirement. However, I am still not clear how the settings in http-server.xml get processed when mTLS config is specified? As in, is there an auto generated http-server.xml when mtls config is specified via VESPA_TLS_CONFIG_FILE?

adarshaj commented 2 years ago

@tokle - I followed your guideline and created the following files: /opt/vespa/conf/configserver-app/http-server.xml:

<server port="19072" id="configserver-ssl">
  <config name="jdisc.http.connector">
    <ssl>
      <enabled>true</enabled>
      <privateKeyFile>/opt/vespa/conf/configserver-app/tls/private-key.pem</privateKeyFile>
      <certificateFile>/opt/vespa/conf/configserver-app/tls/certificate.pem</certificateFile>
      <caCertificateFile>/opt/vespa/conf/configserver-app/tls/ca-certificates.pem</caCertificateFile>
    </ssl>
  </config>
</server>

Placed the tls files mentioned above with right permissions.

The files mentioned in the ssl config above are different than the ones specified in VESPA_TLS_CONFIG_FILE -- this is to just distinguish server running on port 19071 and port 19072.

After restarting the node, I did see that server was started on port 19072. However, it did not pickup the ssl config, it was serving the same certificates as 19071 (which was specified in VESPA_TLS_CONFIG_FILE).

tokle commented 2 years ago

Hi @adarshaj,

Sorry, a bit of confusion from my side here. While it is possible to use the jdisc.http.connector config, it will requires some extra steps. I think you will be better off using the ssl-syntax directly. Using the http-server.xml file you can include ssl configuration as described in https://docs.vespa.ai/en/jdisc/http-server-and-filters.html#ssl.

So your example would be:

<server port="19072" id="configserver-ssl">
  <ssl>
    <private-key-file>/opt/vespa/conf/configserver-app/tls/private-key.pem</private-key-file>
    <certificate-file>/opt/vespa/conf/configserver-app/tls/certificate.pem</certificate-file>
    <ca-certificates-file>/opt/vespa/conf/configserver-app/tls/ca-certificates.pem</ca-certificates-file>
  </ssl>
</server>

Note that you cannot override the port 19071 with this. If you want to be sure no node access the APIs there, you can add a rejecting filter.

adarshaj commented 2 years ago

Thanks @tokle 🙏 ! Your suggestion works perfectly as intended 🎉 !

I am not sure if this issue needs to be closed (may be docs are to be updated -- say in advanced configuration section).. Feel free to close..