diff --git a/CMakeLists.txt b/CMakeLists.txt index b6b32faaff7..37f20cc5519 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -738,6 +738,7 @@ configure_file(include/ts/apidefs.h.in include/ts/apidefs.h) add_subdirectory(src/tscpp/api) add_subdirectory(src/tsutil) +add_subdirectory(src/config) add_subdirectory(src/tscore) add_subdirectory(src/records) add_subdirectory(src/iocore) diff --git a/configs/records.yaml.default.in b/configs/records.yaml.default.in index 225ae802399..67bd8e6d6ed 100644 --- a/configs/records.yaml.default.in +++ b/configs/records.yaml.default.in @@ -199,7 +199,7 @@ records: ############################################################################## # SSL Termination. Docs: # https://docs.trafficserver.apache.org/en/latest/admin-guide/files/records.yaml.en.html#client-related-configuration -# https://docs.trafficserver.apache.org/en/latest/admin-guide/files/ssl_multicert.config.en.html +# https://docs.trafficserver.apache.org/en/latest/admin-guide/files/ssl_multicert.yaml.en.html ############################################################################## verify: server: diff --git a/configs/ssl_multicert.config.default b/configs/ssl_multicert.yaml.default similarity index 56% rename from configs/ssl_multicert.config.default rename to configs/ssl_multicert.yaml.default index 43eb43e4cb5..c5eac93a629 100644 --- a/configs/ssl_multicert.config.default +++ b/configs/ssl_multicert.yaml.default @@ -1,12 +1,12 @@ # -# ssl_multicert.config +# ssl_multicert.yaml # # Documentation: -# https://docs.trafficserver.apache.org/en/latest/admin-guide/files/ssl_multicert.config.en.html +# https://docs.trafficserver.apache.org/en/latest/admin-guide/files/ssl_multicert.yaml.en.html # # Allows a TLS certificate and private key to be tied to a specific # hostname or IP address. At load time, the certificate is parsed to -# extract the subject CN and all the DNS subjectAltNames. The +# extract the subject CN and all the DNS subjectAltNames. The # certificate will be presented for connections requesting any of the # hostnames found in the certificate. Wildcard names in the certificates # are supported, but only of the form '*.domain.com', ie. where '*' @@ -18,7 +18,11 @@ # # Fields: # -# dest_ip=ADDRESS +# ssl_cert_name: FILENAME +# The name of the file containing the TLS certificate. This is the +# only field that is required to be present (unless action is tunnel). +# +# dest_ip: ADDRESS # The IP (v4 or v6) address that the certificate should be presented # on. This is now only used as a fallback in the case that the TLS # ServerNameIndication extension is not supported. If ADDRESS is @@ -30,37 +34,58 @@ # accepted on the specified port. IPv6 addresses must be enclosed by # square brackets if they have a port, eg, [::1]:80. # -# ssl_key_name=FILENAME +# ssl_key_name: FILENAME # The name of the file containing the private key for this certificate. # If the key is contained in the certificate file, this field can be # omitted. # -# ssl_ca_name=FILENAME +# ssl_ca_name: FILENAME # If your certificates have different Certificate Authorities, you # can optionally specify the corresponding file here. # -# ssl_cert_name=FILENAME -# The name of the file containing the TLS certificate. This is the -# only field that is required to be present. +# ssl_ocsp_name: FILENAME +# The name of the file containing the OCSP response for stapling. # -# ssl_key_dialog=[builtin|exec:/path/to/program] +# ssl_key_dialog: builtin|exec:/path/to/program # Method used to provide a pass phrase for encrypted private keys. # Two options are supported: builtin and exec # builtin - Requests passphrase via stdin/stdout. Useful for debugging. # exec: - Executes a program and uses the stdout output for the pass # phrase. # -# action=[tunnel] -# If the tunnel matches this line, traffic server will not participate -# in the handshake. But rather it will blind tunnel the SSL connection. -# If the connection is identified by server name, an openSSL patch must -# be applied to enable this functionality. See TS-3006 for details. -# -# Examples: -# ssl_cert_name=foo.pem -# dest_ip=* ssl_cert_name=bar.pem ssl_key_name=barKey.pem -# dest_ip=209.131.48.79 ssl_cert_name=server.pem ssl_key_name=serverKey.pem -# dest_ip=10.0.0.1:99 ssl_cert_name=port99.pem -# ssl_cert_name=foo.pem ssl_key_dialog="exec:/usr/bin/mypass foo 'ba r'" -# ssl_cert_name=foo.pem action=tunnel -# ssl_cert_name=wildcardcert.pem ssl_key_name=privkey.pem +# ssl_ticket_enabled: 0|1 +# Enable or disable session tickets for this certificate. +# +# ssl_ticket_number: NUMBER +# Number of session tickets to issue for new TLSv1.3 connections. +# +# action: tunnel +# If the connection matches this entry, traffic server will not participate +# in the handshake. Instead, it will blind tunnel the SSL connection. +# +# Example configuration: +# +# ssl_multicert: +# - ssl_cert_name: server.pem +# +# - ssl_cert_name: bar.pem +# ssl_key_name: barKey.pem +# dest_ip: "*" +# +# - ssl_cert_name: server.pem +# ssl_key_name: serverKey.pem +# dest_ip: "209.131.48.79" +# +# - ssl_cert_name: port99.pem +# dest_ip: "10.0.0.1:99" +# +# - ssl_cert_name: foo.pem +# ssl_key_dialog: "exec:/usr/bin/mypass foo 'ba r'" +# +# - action: tunnel +# dest_ip: "192.168.1.1" +# +# - ssl_cert_name: wildcardcert.pem +# ssl_key_name: privkey.pem + +ssl_multicert: [] diff --git a/doc/admin-guide/files/index.en.rst b/doc/admin-guide/files/index.en.rst index 1ce15d62421..848729fb76a 100644 --- a/doc/admin-guide/files/index.en.rst +++ b/doc/admin-guide/files/index.en.rst @@ -34,7 +34,7 @@ Configuration Files records.yaml.en remap.config.en splitdns.config.en - ssl_multicert.config.en + ssl_multicert.yaml.en sni.yaml.en storage.config.en strategies.yaml.en @@ -72,7 +72,7 @@ Configuration Files :doc:`splitdns.config.en` Configures DNS servers to use under specific conditions. -:doc:`ssl_multicert.config.en` +:doc:`ssl_multicert.yaml.en` Configures |TS| to use different server certificates for SSL termination when listening on multiple addresses or when clients employ SNI. diff --git a/doc/admin-guide/files/records.yaml.en.rst b/doc/admin-guide/files/records.yaml.en.rst index 835e205275b..5a5eb846d0b 100644 --- a/doc/admin-guide/files/records.yaml.en.rst +++ b/doc/admin-guide/files/records.yaml.en.rst @@ -3974,24 +3974,24 @@ SSL Termination ===== ====================================================================== -.. ts:cv:: CONFIG proxy.config.ssl.server.multicert.filename STRING ssl_multicert.config +.. ts:cv:: CONFIG proxy.config.ssl.server.multicert.filename STRING ssl_multicert.yaml :deprecated: - The location of the :file:`ssl_multicert.config` file, relative + The location of the :file:`ssl_multicert.yaml` file, relative to the |TS| configuration directory. In the following example, if the |TS| configuration directory is `/etc/trafficserver`, the |TS| SSL configuration file and the corresponding certificates are located in `/etc/trafficserver/ssl`:: - CONFIG proxy.config.ssl.server.multicert.filename STRING ssl/ssl_multicert.config + CONFIG proxy.config.ssl.server.multicert.filename STRING ssl/ssl_multicert.yaml CONFIG proxy.config.ssl.server.cert.path STRING etc/trafficserver/ssl CONFIG proxy.config.ssl.server.private_key.path STRING etc/trafficserver/ssl .. ts:cv:: CONFIG proxy.config.ssl.server.multicert.exit_on_load_fail INT 1 By default (``1``), |TS| will not start unless all the SSL certificates listed in the - :file:`ssl_multicert.config` file successfully load. If false (``0``), SSL certificate + :file:`ssl_multicert.yaml` file successfully load. If false (``0``), SSL certificate load failures will not prevent |TS| from starting. .. ts:cv:: CONFIG proxy.config.ssl.server.cert.path STRING /config @@ -4000,21 +4000,21 @@ SSL Termination and validation new SSL sessions. If this is a relative path, it is appended to the |TS| installation PREFIX. All certificates and certificate chains listed in - :file:`ssl_multicert.config` will be loaded relative to this path. + :file:`ssl_multicert.yaml` will be loaded relative to this path. .. ts:cv:: CONFIG proxy.config.ssl.server.private_key.path STRING NULL The location of the SSL certificate private keys. Change this variable only if the private key is not located in the SSL certificate file. All private keys listed in - :file:`ssl_multicert.config` will be loaded relative to this + :file:`ssl_multicert.yaml` will be loaded relative to this path. .. ts:cv:: CONFIG proxy.config.ssl.server.cert_chain.filename STRING NULL The name of a file containing a global certificate chain that should be used with every server certificate. This file is only - used if there are certificates defined in :file:`ssl_multicert.config`. + used if there are certificates defined in :file:`ssl_multicert.yaml`. Unless this is an absolute path, it is loaded relative to the path specified by :ts:cv:`proxy.config.ssl.server.cert.path`. @@ -4523,7 +4523,7 @@ OCSP Stapling Configuration The directory path of the prefetched OCSP stapling responses. Change this variable only if you intend to use and administratively maintain prefetched OCSP stapling responses. All stapling responses listed in - :file:`ssl_multicert.config` will be loaded relative to this + :file:`ssl_multicert.yaml` will be loaded relative to this path. HTTP/2 Configuration diff --git a/doc/admin-guide/files/ssl_multicert.config.en.rst b/doc/admin-guide/files/ssl_multicert.yaml.en.rst similarity index 76% rename from doc/admin-guide/files/ssl_multicert.config.en.rst rename to doc/admin-guide/files/ssl_multicert.yaml.en.rst index d78bc75fc16..2c27d7e4a98 100644 --- a/doc/admin-guide/files/ssl_multicert.config.en.rst +++ b/doc/admin-guide/files/ssl_multicert.yaml.en.rst @@ -15,13 +15,13 @@ specific language governing permissions and limitations under the License. -==================== -ssl_multicert.config -==================== +================== +ssl_multicert.yaml +================== -.. configfile:: ssl_multicert.config +.. configfile:: ssl_multicert.yaml -The :file:`ssl_multicert.config` file lets you configure Traffic +The :file:`ssl_multicert.yaml` file lets you configure Traffic Server to use multiple SSL server certificates to terminate the SSL sessions. If you have a Traffic Server system with more than one IP address assigned to it, then you can assign a different SSL @@ -36,17 +36,17 @@ found in the certificate. Wildcard names are supported, but only of the form `*.domain.com`, ie. where `*` is the leftmost domain component. -Changes to :file:`ssl_multicert.config` can be applied to a running +Changes to :file:`ssl_multicert.yaml` can be applied to a running Traffic Server using :option:`traffic_ctl config reload`. Format ====== -Each :file:`ssl_multicert.config` line consists of a sequence of -`key=value` fields that specify how Traffic Server should use a -particular SSL certificate. +The :file:`ssl_multicert.yaml` file uses YAML format with a top-level +``ssl_multicert`` key containing a sequence of certificate entries. +Each entry is a mapping with the following keys: -ssl_cert_name=FILENAME[,FILENAME ...] +ssl_cert_name: FILENAME[,FILENAME ...] The name of the file containing the TLS certificate. *FILENAME* is located relative to the directory specified by the :ts:cv:`proxy.config.ssl.server.cert.path` configuration variable. @@ -68,9 +68,10 @@ ssl_cert_name=FILENAME[,FILENAME ...] You can also configure multiple leaf certificates in a same chain with OpenSSL 1.0.1. - This is the only field that is required to be present. + This is the only field that is required to be present (unless + ``action`` is set to ``tunnel``). -dest_ip=ADDRESS (optional) +dest_ip: ADDRESS (optional) The IP (v4 or v6) address that the certificate should be presented on. This is now only used as a fallback in the case that the TLS ServerNameIndication extension is not supported. If *ADDRESS* is @@ -81,19 +82,19 @@ dest_ip=ADDRESS (optional) IPv6 addresses must be enclosed by square brackets if they have a port, eg, [::1]:80. Care should be taken to make each ADDRESS unique. -ssl_key_name=FILENAME (optional) +ssl_key_name: FILENAME (optional) The name of the file containing the private key for this certificate. If the key is contained in the certificate file, this field can be omitted, otherwise *FILENAME* is resolved relative to the :ts:cv:`proxy.config.ssl.server.private_key.path` configuration variable. -ssl_ca_name=FILENAME (optional) +ssl_ca_name: FILENAME (optional) If the certificate is issued by an authority that is not in the system CA bundle, additional certificates may be needed to validate the certificate chain. *FILENAME* is resolved relative to the :ts:cv:`proxy.config.ssl.CA.cert.path` configuration variable. -ssl_ocsp_name=FILENAME (optional) +ssl_ocsp_name: FILENAME (optional) The name of the file containing the prefetched OCSP stapling response for this certificate. This field can be omitted to let trafficserver fetch OCSP responses dynamically. Otherwise, when included, the administrator is @@ -101,16 +102,16 @@ ssl_ocsp_name=FILENAME (optional) relative to the :ts:cv:`proxy.config.ssl.ocsp.response.path` configuration variable. -ssl_ticket_enabled=1|0 (optional) +ssl_ticket_enabled: 1|0 (optional) Enable RFC 5077 stateless TLS session tickets. To support this, OpenSSL should be upgraded to version 0.9.8f or higher. This option must be set to `0` to disable session ticket support. -ssl_ticket_number=INTEGER (optional) +ssl_ticket_number: INTEGER (optional) Specifies the number of TLSv1.3 session tickets that are issued. This defaults to 2 (the OpenSSL default) -ssl_key_dialog=builtin|"exec:/path/to/program [args]" (optional) +ssl_key_dialog: builtin|"exec:/path/to/program [args]" (optional) Method used to provide a pass phrase for encrypted private keys. If the pass phrase is incorrect, SSL negotiation for this dest_ip will fail for clients who attempt to connect. @@ -128,6 +129,10 @@ ssl_key_dialog=builtin|"exec:/path/to/program [args]" (optional) program runs a security check to ensure that the system is not compromised by an attacker before providing the pass phrase. +action: tunnel (optional) + If set to ``tunnel``, Traffic Server will not participate in the + TLS handshake and will blind tunnel the connection instead. + Certificate Selection ===================== @@ -163,19 +168,27 @@ are terminated with the ``default.pem`` certificate. Since the private key is included in the certificate files, no private key name is specified. -:: +.. code-block:: yaml + + ssl_multicert: + - ssl_cert_name: server.pem + dest_ip: "111.11.11.1" + + - ssl_cert_name: server1.pem + dest_ip: "11.1.1.1" - dest_ip=111.11.11.1 ssl_cert_name=server.pem - dest_ip=11.1.1.1 ssl_cert_name=server1.pem - dest_ip=* ssl_cert_name=default.pem + - ssl_cert_name: default.pem + dest_ip: "*" The following example configures Traffic Server to use the ECDSA certificate chain ``ecdsa.pem`` or RSA certificate chain ``rsa.pem`` for all requests. -:: +.. code-block:: yaml - dest_ip=* ssl_cert_name=ecdsa.pem,rsa.pem + ssl_multicert: + - ssl_cert_name: ecdsa.pem,rsa.pem + dest_ip: "*" The following example configures Traffic Server to use the ECDSA certificate chain ``ecdsa.pem`` or RSA certificate chain ``rsa.pem`` @@ -183,35 +196,46 @@ for all requests, the public key and private key are in separate PEM files. Note that the number of files in ssl_key_name must match the files in ssl_cert_name, and they should be presented in the same order. -:: +.. code-block:: yaml - dest_ip=* ssl_cert_name=ecdsa_pub.pem,rsa_pub.pem ssl_key_name=ecdsa_private.pem,rsa_private.pem + ssl_multicert: + - ssl_cert_name: ecdsa_pub.pem,rsa_pub.pem + ssl_key_name: ecdsa_private.pem,rsa_private.pem + dest_ip: "*" The following example configures Traffic Server to use the SSL certificate ``server.pem`` and the private key ``serverKey.pem`` for all requests to port 8443 on IP address 111.11.11.1. The ``general.pem`` certificate is used for server name matches. -:: +.. code-block:: yaml - dest_ip=111.11.11.1:8443 ssl_cert_name=server.pem ssl_key_name=serverKey.pem ssl_cert_name=general.pem + ssl_multicert: + - ssl_cert_name: server.pem,general.pem + ssl_key_name: serverKey.pem + dest_ip: "111.11.11.1:8443" The following example configures Traffic Server to use the SSL certificate ``server.pem`` for all requests to the IP address -111.11.11.1. Session tickets are enabled with a persistent ticket -key. +111.11.11.1. Session tickets are enabled. -:: +.. code-block:: yaml - dest_ip=111.11.11.1 ssl_cert_name=server.pem ssl_ticket_enabled=1 ticket_key_name=ticket.key + ssl_multicert: + - ssl_cert_name: server.pem + dest_ip: "111.11.11.1" + ssl_ticket_enabled: 1 The following example configures Traffic Server to use the SSL certificate ``server.pem`` and disable session tickets for all requests to the IP address 111.11.11.1. -:: +.. code-block:: yaml - dest_ip=111.11.11.1 ssl_cert_name=server.pem ssl_ticket_enabled=0 + ssl_multicert: + - ssl_cert_name: server.pem + dest_ip: "111.11.11.1" + ssl_ticket_enabled: 0 The following examples configure Traffic Server to use the SSL certificate ``server.pem`` which includes an encrypted private key. @@ -220,7 +244,27 @@ parameter (foo) in the first example, and with two parameters (foo) and (ba r) in the second example, the program (mypass) will return the pass phrase to decrypt the keys. -:: +.. code-block:: yaml + + ssl_multicert: + - ssl_cert_name: server1.pem + ssl_key_dialog: "exec:/usr/bin/mypass foo" + + - ssl_cert_name: server2.pem + ssl_key_dialog: "exec:/usr/bin/mypass foo 'ba r'" + +Migration from ssl_multicert.config +=================================== + +The ``traffic_ctl`` command can be used to convert pre-11.x ``ssl_multicert.config`` +files to the new YAML format: + +.. code-block:: bash + + traffic_ctl config convert ssl_multicert ssl_multicert.config ssl_multicert.yaml + +To output to stdout instead of a file, use ``-`` as the output path: + +.. code-block:: bash - ssl_cert_name=server1.pem ssl_key_dialog="exec:/usr/bin/mypass foo" - ssl_cert_name=server2.pem ssl_key_dialog="exec:/usr/bin/mypass foo 'ba r'" + traffic_ctl config convert ssl_multicert ssl_multicert.config - diff --git a/doc/admin-guide/security/index.en.rst b/doc/admin-guide/security/index.en.rst index 829392e2425..cec71bca1b4 100644 --- a/doc/admin-guide/security/index.en.rst +++ b/doc/admin-guide/security/index.en.rst @@ -121,7 +121,7 @@ Client/|TS| connections, you must do the following: private_key: path: /opt/ts/etc/ssl/keys -#. Add an entry to :file:`ssl_multicert.config` for each certificate and key +#. Add an entry to :file:`ssl_multicert.yaml` for each certificate and key which your |TS| system will be using to terminate SSL connections with clients. :: @@ -302,7 +302,7 @@ a ticket key file as a reverse queue in 48-byte chunks. #. *Optional*: Delete the last ticket key from the ticket key file. -#. Touch :file:`ssl_multicert.config` to indicate that the SSL configuration is stale. +#. Touch :file:`ssl_multicert.yaml` to indicate that the SSL configuration is stale. #. Run the command :option:`traffic_ctl config reload` to apply the new ticket key. @@ -335,7 +335,7 @@ Authority Information Access field of the signed certificate. For example:: CA Issuers - URI:http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt |TS| can also use prefetched OCSP stapling responses if ssl_ocsp_name parameter -is used in :file:`ssl_multicert.config`. Take into account that when using prefetched +is used in :file:`ssl_multicert.yaml`. Take into account that when using prefetched OCSP stapling responses, |TS| will not refresh them and it should be done externally. This can be done using OpenSSL:: diff --git a/doc/admin-guide/security/mtls.en.rst b/doc/admin-guide/security/mtls.en.rst index 6a850459730..e602d3d1cf2 100644 --- a/doc/admin-guide/security/mtls.en.rst +++ b/doc/admin-guide/security/mtls.en.rst @@ -161,6 +161,6 @@ From there you can verify via your origins that the updated certificates are bei traffic_ctl config reload -If the contents of the certificate files change but the names of the files do not, you may need to touch ssl_multicert.config +If the contents of the certificate files change but the names of the files do not, you may need to touch ssl_multicert.yaml (for server certs) and sni.yaml (for client certs). diff --git a/doc/appendices/command-line/traffic_ctl.en.rst b/doc/appendices/command-line/traffic_ctl.en.rst index 55dbee55707..e08f1b117a8 100644 --- a/doc/appendices/command-line/traffic_ctl.en.rst +++ b/doc/appendices/command-line/traffic_ctl.en.rst @@ -365,6 +365,35 @@ Display the current value of a configuration record. Display information about the registered files in |TS|. This includes the full file path, config record name, parent config (if any) if needs root access and if the file is required in |TS|. +.. program:: traffic_ctl config +.. option:: ssl-multicert show [--yaml | --json] + + Display the current ``ssl_multicert.yaml`` configuration. By default, output is in YAML format. + Use ``--json`` or ``-j`` to output in JSON format. + + .. option:: --yaml, -y + + Output in YAML format (default). + + .. option:: --json, -j + + Output in JSON format. + + Example: + + .. code-block:: bash + + $ traffic_ctl config ssl-multicert show + ssl_multicert: + - ssl_cert_name: server.pem + dest_ip: "*" + ssl_key_name: server.key + + .. code-block:: bash + + $ traffic_ctl config ssl-multicert show --json + {"ssl_multicert": [{"ssl_cert_name": "server.pem", "dest_ip": "*", "ssl_key_name": "server.key"}]} + .. _traffic-control-command-metric: traffic_ctl metric diff --git a/doc/developer-guide/api/functions/TSSslContext.en.rst b/doc/developer-guide/api/functions/TSSslContext.en.rst index 08373657c12..22f5ca99826 100644 --- a/doc/developer-guide/api/functions/TSSslContext.en.rst +++ b/doc/developer-guide/api/functions/TSSslContext.en.rst @@ -38,11 +38,11 @@ Description =========== :func:`TSSslContextFindByName` searches for a SSL server context -created from :file:`ssl_multicert.config`, matching against the +created from :file:`ssl_multicert.yaml`, matching against the server :arg:`name`. :func:`TSSslContextFindByAddr` searches for a SSL server context -created from :file:`ssl_multicert.config` matching against the server +created from :file:`ssl_multicert.yaml` matching against the server :arg:`address`. diff --git a/doc/developer-guide/api/functions/TSSslServerCertUpdate.en.rst b/doc/developer-guide/api/functions/TSSslServerCertUpdate.en.rst index 6ee1f654241..15847d9b1ca 100644 --- a/doc/developer-guide/api/functions/TSSslServerCertUpdate.en.rst +++ b/doc/developer-guide/api/functions/TSSslServerCertUpdate.en.rst @@ -36,7 +36,7 @@ Description =========== :func:`TSSslServerCertUpdate` updates existing server certificates configured in -:file:`ssl_multicert.config` based on the common name in :arg:`cert_path`. if :arg:`key_path` is set +:file:`ssl_multicert.yaml` based on the common name in :arg:`cert_path`. if :arg:`key_path` is set to nullptr, the function will use :arg:`cert_path` for both certificate and private key. :func:`TSSslServerCertUpdate` returns `TS_SUCCESS` only if there exists such a mapping, :arg:`cert_path` is a valid cert, and the context is updated to use that cert. diff --git a/doc/developer-guide/plugins/hooks-and-transactions/ssl-hooks.en.rst b/doc/developer-guide/plugins/hooks-and-transactions/ssl-hooks.en.rst index e3cdd5a2ded..65fd1996abd 100644 --- a/doc/developer-guide/plugins/hooks-and-transactions/ssl-hooks.en.rst +++ b/doc/developer-guide/plugins/hooks-and-transactions/ssl-hooks.en.rst @@ -84,7 +84,7 @@ TS_SSL_SERVERNAME_HOOK This hook is called if the client provides SNI information in the SSL handshake. If called it will always be called after TS_VCONN_START_HOOK. -The Traffic Server core first evaluates the settings in the ssl_multicert.config file based on the +The Traffic Server core first evaluates the settings in the ssl_multicert.yaml file based on the server name. Then the core SNI callback executes the plugin registered SNI callback code. The plugin callback can access the servername by calling the OpenSSL function SSL_get_servername(). diff --git a/doc/developer-guide/testing/blackbox-testing.en.rst b/doc/developer-guide/testing/blackbox-testing.en.rst index e7827d7692c..a3e49eb027f 100644 --- a/doc/developer-guide/testing/blackbox-testing.en.rst +++ b/doc/developer-guide/testing/blackbox-testing.en.rst @@ -124,7 +124,7 @@ A number of file objects are also defined to help test TrafficServer. Files that - sni.yaml - socks.config - splitdns.config -- ssl_multicert.config +- ssl_multicert.yaml - storage.config - volume.config diff --git a/doc/getting-started/index.en.rst b/doc/getting-started/index.en.rst index c9e8026fec9..83f916093b4 100644 --- a/doc/getting-started/index.en.rst +++ b/doc/getting-started/index.en.rst @@ -342,11 +342,15 @@ rules like:: map https://www.acme.com/ http://localhost:8080/ map https://static.acme.com/ https://origin-static.acme.com/ -This will require installing a certificate, and adding a line to -:file:`ssl_multicert.config`. Assuming the cert has the static.acme.com alternate -name, and that cert should be presented by default:: +This will require installing a certificate, and adding an entry to +:file:`ssl_multicert.yaml`. Assuming the cert has the static.acme.com alternate +name, and that cert should be presented by default: - dest_ip=* ssl_cert_name=/path/to/secret/privatekey/acme.rsa +.. code-block:: yaml + + ssl_multicert: + - ssl_cert_name: /path/to/secret/privatekey/acme.rsa + dest_ip: "*" Further information about configuring |TS| for TLS can be found :ref:`admin-ssl-termination` section of the documentation. @@ -405,9 +409,12 @@ entries: /cache/trafficserver 500G -:file:`ssl_multicert.config`:: +:file:`ssl_multicert.yaml`: + +.. code-block:: yaml - ssl_cert_name=/path/to/secret/acme.rsa + ssl_multicert: + - ssl_cert_name: /path/to/secret/acme.rsa Configuring A Forward Proxy --------------------------- diff --git a/doc/manpages.cmake.in.py b/doc/manpages.cmake.in.py index 7be62e7db8c..09a289b3ade 100644 --- a/doc/manpages.cmake.in.py +++ b/doc/manpages.cmake.in.py @@ -54,8 +54,8 @@ ('admin-guide/files/sni.yaml.en', 'sni.yaml', u'Traffic Server sni rules configuration file', None, '5'), ('admin-guide/files/splitdns.config.en', 'splitdns.config', u'Traffic Server split DNS configuration file', None, '5'), ( - 'admin-guide/files/ssl_multicert.config.en', 'ssl_multicert.config', u'Traffic Server SSL certificate configuration file', - None, '5'), + 'admin-guide/files/ssl_multicert.yaml.en', 'ssl_multicert.yaml', u'Traffic Server SSL certificate configuration file', None, + '5'), ('admin-guide/files/storage.config.en', 'storage.config', u'Traffic Server cache storage configuration file', None, '5'), ('admin-guide/files/strategies.yaml.en', 'strategies.yaml', u'Traffic Server cache hierarchy configuration file', None, '5'), ('admin-guide/files/volume.config.en', 'volume.config', u'Traffic Server cache volume configuration file', None, '5'), diff --git a/doc/manpages.py b/doc/manpages.py index 6ad2d24311e..f1b5562a853 100644 --- a/doc/manpages.py +++ b/doc/manpages.py @@ -52,8 +52,8 @@ ('admin-guide/files/sni.yaml.en', 'sni.yaml', u'Traffic Server sni rules configuration file', None, '5'), ('admin-guide/files/splitdns.config.en', 'splitdns.config', u'Traffic Server split DNS configuration file', None, '5'), ( - 'admin-guide/files/ssl_multicert.config.en', 'ssl_multicert.config', u'Traffic Server SSL certificate configuration file', - None, '5'), + 'admin-guide/files/ssl_multicert.yaml.en', 'ssl_multicert.yaml', u'Traffic Server SSL certificate configuration file', None, + '5'), ('admin-guide/files/storage.config.en', 'storage.config', u'Traffic Server cache storage configuration file', None, '5'), ('admin-guide/files/strategies.yaml.en', 'strategies.yaml', u'Traffic Server cache hierarchy configuration file', None, '5'), ('admin-guide/files/volume.config.en', 'volume.config', u'Traffic Server cache volume configuration file', None, '5'), diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst index 6ad7a050a64..4ce2609b544 100644 --- a/doc/release-notes/upgrading.en.rst +++ b/doc/release-notes/upgrading.en.rst @@ -181,6 +181,18 @@ The following :file:`records.yaml` changes have been made: system. - The records.yaml entry ``proxy.config.plugin.compiler_path`` has been added to specify an optional compiler tool path for compiling plugins. +The ``ssl_multicert.config`` file has been replaced with +:file:`ssl_multicert.yaml`. The new file uses YAML format with a top-level +``ssl_multicert`` key containing a sequence of certificate entries. Use +``traffic_ctl config convert ssl_multicert`` to convert existing +configuration files: + +.. code-block:: bash + + traffic_ctl config convert ssl_multicert ssl_multicert.config ssl_multicert.yaml + +See :file:`ssl_multicert.yaml` for the new format documentation. + The following changes have been made to the :file:`sni.yaml` file: - ``disable_h2`` has been removed. Use ``http2`` with :code:`off` instead. diff --git a/doc/release-notes/whats-new.en.rst b/doc/release-notes/whats-new.en.rst index 4d9e297c869..9e8f813aad5 100644 --- a/doc/release-notes/whats-new.en.rst +++ b/doc/release-notes/whats-new.en.rst @@ -108,6 +108,8 @@ Configuration * Added :ts:cv:`proxy.config.http.negative_revalidating_list` to configure the list of status codes that apply to the negative revalidating feature +* The ``ssl_multicert.config`` file has been replaced with :file:`ssl_multicert.yaml`. + Use ``traffic_ctl config convert ssl_multicert`` to convert existing configuration files. diff --git a/include/config/config_result.h b/include/config/config_result.h new file mode 100644 index 00000000000..74283deff8e --- /dev/null +++ b/include/config/config_result.h @@ -0,0 +1,77 @@ +/** @file + + Generic configuration parsing result type. + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#pragma once + +#include "swoc/Errata.h" + +namespace config +{ + +/** + * Result of a configuration parse operation. + * + * This template is the standard return type for all configuration parsers in + * the config library. It bundles a parsed configuration value with an errata + * that may contain warnings or errors encountered during parsing. + * + * Design rationale: + * - Parsers can return partial results (value populated) even when warnings + * are present, allowing callers to decide how to handle degraded configs. + * - The ok() method checks whether parsing succeeded without errors, but + * callers should also inspect the errata for warnings. + * - This type is reused across all configuration file types (ssl_multicert, + * etc.) to provide a consistent API. + * + * Example usage: + * @code + * config::SSLMultiCertParser parser; + * auto result = parser.parse("/path/to/ssl_multicert.yaml"); + * if (!result.ok()) { + * // Handle error + * return; + * } + * for (const auto& entry : result.value) { + * // Use parsed entries + * } + * @endcode + * + * @tparam T The configuration type (e.g., SSLMultiCertConfig). + */ +template struct ConfigResult { + T value; ///< The parsed configuration value. + swoc::Errata errata; ///< Errors or warnings from parsing. + + /** + * Check if parsing succeeded without errors. + * + * @return true if no errors occurred, false otherwise. + */ + bool + ok() const + { + return errata.is_ok(); + } +}; + +} // namespace config diff --git a/include/config/ssl_multicert.h b/include/config/ssl_multicert.h new file mode 100644 index 00000000000..b7984eba301 --- /dev/null +++ b/include/config/ssl_multicert.h @@ -0,0 +1,128 @@ +/** @file + + SSL Multi-Certificate configuration parsing and marshalling. + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#pragma once + +#include +#include +#include +#include + +#include "config/config_result.h" + +namespace config +{ + +/** + * Represents a single certificate entry in ssl_multicert configuration. + */ +struct SSLMultiCertEntry { + std::string ssl_cert_name; ///< Certificate file name (required unless action is tunnel). + std::string dest_ip{"*"}; ///< IP address to match (default "*"). + std::string ssl_key_name; ///< Private key file name (optional). + std::string ssl_ca_name; ///< CA certificate file name (optional). + std::string ssl_ocsp_name; ///< OCSP response file name (optional). + std::string ssl_key_dialog; ///< Passphrase dialog method (optional). + std::string dest_fqdn; ///< Destination FQDN (optional). + std::string action; ///< Action (e.g., "tunnel"). + std::optional ssl_ticket_enabled; ///< Session ticket enabled (optional). + std::optional ssl_ticket_number; ///< Number of session tickets (optional). +}; + +/// A configuration is a vector of certificate entries. +using SSLMultiCertConfig = std::vector; + +/** + * Parser for ssl_multicert configuration files. + * + * Supports both YAML (.yaml) and legacy (.config) formats with automatic + * format detection. + */ +class SSLMultiCertParser +{ +public: + /** + * Parse an ssl_multicert configuration file. + * + * The format is auto-detected based on file extension and content. + * + * @param[in] filename Path to the configuration file. + * @return ConfigResult containing the parsed entries or errors. + */ + ConfigResult parse(std::string const &filename); + +private: + enum class Format { YAML, Legacy }; + + /** + * Detect the configuration format from content and filename. + * + * @param[in] content The configuration content. + * @param[in] filename The filename (used for extension-based detection). + * @return The detected format. + */ + Format detect_format(std::string_view content, std::string const &filename); + + /** + * Parse YAML-formatted configuration content. + * + * @param[in] content The YAML content. + * @return ConfigResult containing the parsed entries or errors. + */ + ConfigResult parse_yaml(std::string_view content); + + /** + * Parse legacy (.config) formatted configuration content. + * + * @param[in] content The legacy config content. + * @return ConfigResult containing the parsed entries or errors. + */ + ConfigResult parse_legacy(std::string_view content); +}; + +/** + * Marshaller for ssl_multicert configuration. + * + * Serializes configuration to YAML or JSON format. + */ +class SSLMultiCertMarshaller +{ +public: + /** + * Serialize configuration to YAML format. + * + * @param[in] config The configuration to serialize. + * @return YAML string representation. + */ + std::string to_yaml(SSLMultiCertConfig const &config); + + /** + * Serialize configuration to JSON format. + * + * @param[in] config The configuration to serialize. + * @return JSON string representation. + */ + std::string to_json(SSLMultiCertConfig const &config); +}; + +} // namespace config diff --git a/include/iocore/net/SSLMultiCertConfigLoader.h b/include/iocore/net/SSLMultiCertConfigLoader.h index 42187b86269..b2b7fc246eb 100644 --- a/include/iocore/net/SSLMultiCertConfigLoader.h +++ b/include/iocore/net/SSLMultiCertConfigLoader.h @@ -39,7 +39,7 @@ struct SSLMultiCertConfigParams; struct SSLLoadingContext; /** - @brief Load SSL certificates from ssl_multicert.config and setup SSLCertLookup for SSLCertificateConfig + @brief Load SSL certificates from ssl_multicert.yaml and setup SSLCertLookup for SSLCertificateConfig */ class SSLMultiCertConfigLoader { diff --git a/include/tscore/Filenames.h b/include/tscore/Filenames.h index 90ae0485df9..716f9e530ff 100644 --- a/include/tscore/Filenames.h +++ b/include/tscore/Filenames.h @@ -39,7 +39,7 @@ namespace filename constexpr const char *SOCKS = "socks.config"; constexpr const char *PARENT = "parent.config"; constexpr const char *REMAP = "remap.config"; - constexpr const char *SSL_MULTICERT = "ssl_multicert.config"; + constexpr const char *SSL_MULTICERT = "ssl_multicert.yaml"; constexpr const char *SPLITDNS = "splitdns.config"; constexpr const char *SNI = "sni.yaml"; constexpr const char *JSONRPC = "jsonrpc.yaml"; diff --git a/src/config/CMakeLists.txt b/src/config/CMakeLists.txt new file mode 100644 index 00000000000..141a7f16063 --- /dev/null +++ b/src/config/CMakeLists.txt @@ -0,0 +1,51 @@ +####################### +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor license +# agreements. See the NOTICE file distributed with this work for additional information regarding +# copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +# or implied. See the License for the specific language governing permissions and limitations under +# the License. +# +####################### + +set(CONFIG_PUBLIC_HEADERS ${PROJECT_SOURCE_DIR}/include/config/config_result.h + ${PROJECT_SOURCE_DIR}/include/config/ssl_multicert.h +) + +add_library(tsconfig ssl_multicert.cc) + +add_library(ts::config ALIAS tsconfig) + +set_target_properties(tsconfig PROPERTIES POSITION_INDEPENDENT_CODE TRUE PUBLIC_HEADER "${CONFIG_PUBLIC_HEADERS}") + +target_include_directories(tsconfig PUBLIC ${PROJECT_SOURCE_DIR}/include) + +target_link_libraries(tsconfig PUBLIC libswoc::libswoc yaml-cpp::yaml-cpp) + +if(BUILD_SHARED_LIBS) + install( + TARGETS tsconfig + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/config + ) +else() + install(FILES ${CONFIG_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/config) +endif() + +clang_tidy_check(tsconfig) + +if(BUILD_TESTING) + add_executable(test_tsconfig unit_tests/test_ssl_multicert.cc) + + target_link_libraries(test_tsconfig PRIVATE tsconfig Catch2::Catch2WithMain) + + add_catch2_test(NAME test_tsconfig COMMAND $) +endif() diff --git a/src/config/README.md b/src/config/README.md new file mode 100644 index 00000000000..9360062df20 --- /dev/null +++ b/src/config/README.md @@ -0,0 +1,122 @@ +# Configuration Parsing Library + +This directory contains a shared configuration parsing and marshalling framework +used by various ATS components including `traffic_server` and `traffic_ctl`. + +## Architecture Overview + +Each configuration file type (ssl_multicert, etc.) follows the same pattern: + +``` +include/config/.h - Header with data types, parser, marshaller +src/config/.cc - Implementation +``` + +### Components + +For each configuration type, there are three main components: + +1. **Entry struct** - A POD (plain old data) type representing a single + configuration entry (e.g., `SSLMultiCertEntry`). + +2. **Parser class** - Reads configuration files and returns parsed entries. + Supports both YAML and legacy formats with automatic format detection. + +3. **Marshaller class** - Serializes configuration to YAML or JSON format. + +### Example: ssl_multicert + +``` +include/config/ssl_multicert.h +├── SSLMultiCertEntry - Single certificate entry +├── SSLMultiCertConfig - Vector of entries (type alias) +├── ConfigResult - Parse result with error handling +├── SSLMultiCertParser - Parser for .yaml and .config formats +└── SSLMultiCertMarshaller - Serializer to YAML/JSON +``` + +## Usage + +### Parsing a Configuration File + +```cpp +#include "config/ssl_multicert.h" + +config::SSLMultiCertParser parser; +auto result = parser.parse("/path/to/ssl_multicert.yaml"); + +if (!result.ok()) { + // Handle error - result.errata contains error details + return; +} + +for (const auto& entry : result.value) { + // Use entry.ssl_cert_name, entry.dest_ip, etc. +} +``` + +### Marshalling to YAML/JSON + +```cpp +config::SSLMultiCertMarshaller marshaller; +std::string yaml = marshaller.to_yaml(result.value); +std::string json = marshaller.to_json(result.value); +``` + +## Format Detection + +The parser automatically detects the configuration format: + +1. **By file extension**: `.yaml`/`.yml` → YAML, `.config` → Legacy +2. **By content inspection**: Looks for `ssl_multicert:` (YAML) vs `key=value` (Legacy) + +## Adding a New Configuration Type + +To add support for a new configuration (maybe, `logging.yaml`): + +1. Create `include/config/logging.h`: + - Define `LoggingEntry` struct with fields matching the config + - Define `LoggingConfig = std::vector` + - Declare `LoggingParser` and `LoggingMarshaller` classes + +2. Create `src/config/logging.cc`: + - Implement YAML parsing using yaml-cpp + - Implement legacy format parsing if applicable + - Implement YAML and JSON marshalling + +3. Update `src/config/CMakeLists.txt`: + - Add `logging.cc` to the library sources + - Add header to `CONFIG_PUBLIC_HEADERS` + +4. Integrate with consumers (traffic_ctl, traffic_server, etc.) + +## Error Handling + +All parsers return `ConfigResult` which contains: + +- `value` - The parsed configuration (valid even on partial failure) +- `errata` - Error/warning information using `swoc::Errata` +- `ok()` - Returns true if no errors occurred + +```cpp +if (!result.ok()) { + if (!result.errata.empty()) { + std::cerr << result.errata.front().text() << std::endl; + } +} +``` + +## Dependencies + +- **yaml-cpp** - YAML parsing +- **libswoc** - Error handling (`swoc::Errata`) + +## Running Unit Tests + +Build with testing enabled and run: + +```bash +cmake -B build -DBUILD_TESTING=ON ... +cmake --build build --target test_tsconfig +ctest --test-dir build -R test_tsconfig +``` diff --git a/src/config/ssl_multicert.cc b/src/config/ssl_multicert.cc new file mode 100644 index 00000000000..5dfdf486e15 --- /dev/null +++ b/src/config/ssl_multicert.cc @@ -0,0 +1,374 @@ +/** @file + + SSL Multi-Certificate configuration parsing and marshalling implementation. + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "config/ssl_multicert.h" + +#include +#include +#include +#include + +#include + +#include "swoc/swoc_file.h" +#include "swoc/TextView.h" +#include "tsutil/ts_diag_levels.h" + +namespace +{ + +constexpr swoc::Errata::Severity ERRATA_NOTE_SEV{static_cast(DL_Note)}; +constexpr swoc::Errata::Severity ERRATA_WARN_SEV{static_cast(DL_Warning)}; +constexpr swoc::Errata::Severity ERRATA_ERROR_SEV{static_cast(DL_Error)}; + +// YAML key names. +constexpr char KEY_SSL_CERT_NAME[] = "ssl_cert_name"; +constexpr char KEY_DEST_IP[] = "dest_ip"; +constexpr char KEY_SSL_KEY_NAME[] = "ssl_key_name"; +constexpr char KEY_SSL_CA_NAME[] = "ssl_ca_name"; +constexpr char KEY_SSL_OCSP_NAME[] = "ssl_ocsp_name"; +constexpr char KEY_SSL_KEY_DIALOG[] = "ssl_key_dialog"; +constexpr char KEY_DEST_FQDN[] = "dest_fqdn"; +constexpr char KEY_SSL_TICKET_ENABLED[] = "ssl_ticket_enabled"; +constexpr char KEY_SSL_TICKET_NUMBER[] = "ssl_ticket_number"; +constexpr char KEY_ACTION[] = "action"; +constexpr char KEY_SSL_MULTICERT[] = "ssl_multicert"; + +std::set const valid_keys = { + KEY_SSL_CERT_NAME, KEY_DEST_IP, KEY_SSL_KEY_NAME, KEY_SSL_CA_NAME, KEY_SSL_OCSP_NAME, + KEY_SSL_KEY_DIALOG, KEY_DEST_FQDN, KEY_SSL_TICKET_ENABLED, KEY_SSL_TICKET_NUMBER, KEY_ACTION, +}; + +/** + * Parse a line in legacy key=value format, handling quoted values. + * + * Tokenizes on whitespace but respects quoted strings. Each token should be + * key=value format. + */ +std::vector> +parse_legacy_line(swoc::TextView line) +{ + std::vector> result; + + while (!line.ltrim_if(isspace).empty()) { + swoc::TextView key = line.split_prefix_at('='); + if (key.empty()) { + // No '=' found, skip this malformed token by consuming to next whitespace. + line.take_prefix_if(isspace); + continue; + } + key.trim_if(isspace); + + swoc::TextView value; + if (!line.empty() && (line.front() == '"' || line.front() == '\'')) { + // Quoted value: extract until closing quote. + char const quote = line.front(); + line.remove_prefix(1); + value = line.take_prefix_at(quote); + } else { + // Unquoted value: extract until whitespace. + value = line.take_prefix_if(isspace); + } + value.trim_if(isspace); + + if (!key.empty()) { + result.emplace_back(std::string{key}, std::string{value}); + } + } + + return result; +} + +/// Emit a single SSLMultiCertEntry to a YAML::Emitter. +void +emit_entry(YAML::Emitter &emitter, config::SSLMultiCertEntry const &entry) +{ + emitter << YAML::BeginMap; + + auto write_field = [&](char const *key, std::string const &value) { + if (!value.empty()) { + emitter << YAML::Key << key << YAML::Value << value; + } + }; + + auto write_int_field = [&](char const *key, std::optional const &value) { + if (value.has_value()) { + emitter << YAML::Key << key << YAML::Value << value.value(); + } + }; + + write_field(KEY_SSL_CERT_NAME, entry.ssl_cert_name); + write_field(KEY_DEST_IP, entry.dest_ip); + write_field(KEY_SSL_KEY_NAME, entry.ssl_key_name); + write_field(KEY_SSL_CA_NAME, entry.ssl_ca_name); + write_field(KEY_SSL_OCSP_NAME, entry.ssl_ocsp_name); + write_field(KEY_SSL_KEY_DIALOG, entry.ssl_key_dialog); + write_field(KEY_DEST_FQDN, entry.dest_fqdn); + write_field(KEY_ACTION, entry.action); + write_int_field(KEY_SSL_TICKET_ENABLED, entry.ssl_ticket_enabled); + write_int_field(KEY_SSL_TICKET_NUMBER, entry.ssl_ticket_number); + + emitter << YAML::EndMap; +} + +} // namespace + +namespace YAML +{ +template <> struct convert { + static bool + decode(Node const &node, config::SSLMultiCertEntry &entry) + { + if (node[KEY_SSL_CERT_NAME]) { + entry.ssl_cert_name = node[KEY_SSL_CERT_NAME].as(); + } + + if (node[KEY_DEST_IP]) { + entry.dest_ip = node[KEY_DEST_IP].as(); + } + + if (node[KEY_SSL_KEY_NAME]) { + entry.ssl_key_name = node[KEY_SSL_KEY_NAME].as(); + } + + if (node[KEY_SSL_CA_NAME]) { + entry.ssl_ca_name = node[KEY_SSL_CA_NAME].as(); + } + + if (node[KEY_SSL_OCSP_NAME]) { + entry.ssl_ocsp_name = node[KEY_SSL_OCSP_NAME].as(); + } + + if (node[KEY_SSL_KEY_DIALOG]) { + entry.ssl_key_dialog = node[KEY_SSL_KEY_DIALOG].as(); + } + + if (node[KEY_DEST_FQDN]) { + entry.dest_fqdn = node[KEY_DEST_FQDN].as(); + } + + if (node[KEY_SSL_TICKET_ENABLED]) { + entry.ssl_ticket_enabled = node[KEY_SSL_TICKET_ENABLED].as(); + } + + if (node[KEY_SSL_TICKET_NUMBER]) { + entry.ssl_ticket_number = node[KEY_SSL_TICKET_NUMBER].as(); + } + + if (node[KEY_ACTION]) { + entry.action = node[KEY_ACTION].as(); + } + + return true; + } +}; +} // namespace YAML + +namespace config +{ + +ConfigResult +SSLMultiCertParser::parse(std::string const &filename) +{ + std::error_code ec; + std::string content = swoc::file::load(filename, ec); + if (ec) { + // Missing ssl_multicert.* is an acceptable runtime state. + if (ec.value() == ENOENT) { + return {{}, swoc::Errata(ERRATA_WARN_SEV, "Cannot open SSL certificate configuration \"{}\" - {}", filename, ec)}; + } + return {{}, swoc::Errata(ERRATA_ERROR_SEV, "Failed to read SSL certificate configuration from \"{}\" - {}", filename, ec)}; + } + + if (content.empty()) { + return {{}, {}}; + } + + Format const format = detect_format(content, filename); + if (format == Format::YAML) { + return parse_yaml(content); + } + return parse_legacy(content); +} + +SSLMultiCertParser::Format +SSLMultiCertParser::detect_format(std::string_view content, std::string const &filename) +{ + swoc::TextView const fn{filename}; + + // Check file extension first. + if (fn.ends_with(".yaml") || fn.ends_with(".yml")) { + return Format::YAML; + } + if (fn.ends_with(".config")) { + return Format::Legacy; + } + + // Fall back to content inspection. + if (content.find("ssl_multicert:") != std::string_view::npos) { + return Format::YAML; + } + + // Legacy format uses key=value. + if (content.find('=') != std::string_view::npos) { + return Format::Legacy; + } + + // Default to YAML as that's the preferred format. + return Format::YAML; +} + +ConfigResult +SSLMultiCertParser::parse_yaml(std::string_view content) +{ + SSLMultiCertConfig result; + swoc::Errata errata; + std::set unknown_keys; + + try { + YAML::Node config = YAML::Load(std::string(content)); + if (config.IsNull()) { + return {result, std::move(errata)}; + } + + if (!config[KEY_SSL_MULTICERT]) { + return {result, swoc::Errata("expected a toplevel 'ssl_multicert' node")}; + } + + YAML::Node entries = config[KEY_SSL_MULTICERT]; + if (!entries.IsSequence()) { + return {result, swoc::Errata("expected 'ssl_multicert' to be a sequence")}; + } + + for (auto const &entry_node : entries) { + auto const mark = entry_node.Mark(); + if (!entry_node.IsMap()) { + return {result, swoc::Errata(ERRATA_ERROR_SEV, "Expected ssl_multicert entries to be maps at line {}, column {}", mark.line, + mark.column)}; + } + + for (auto const &field : entry_node) { + std::string key = field.first.as(); + if (valid_keys.find(key) == valid_keys.end() && unknown_keys.insert(key).second) { + errata.note(ERRATA_NOTE_SEV, "Ignoring unknown ssl_multicert key '{}' at line {}, column {}", key, mark.line, + mark.column); + } + } + + result.push_back(entry_node.as()); + } + } catch (std::exception const &ex) { + return {result, swoc::Errata("YAML parse error: {}", ex.what())}; + } + + return {result, std::move(errata)}; +} + +ConfigResult +SSLMultiCertParser::parse_legacy(std::string_view content) +{ + SSLMultiCertConfig result; + swoc::Errata errata; + std::set unknown_keys; + swoc::TextView src{content}; + + while (!src.empty()) { + swoc::TextView line = src.take_prefix_at('\n'); + line.trim_if(isspace); + + // Skip empty lines and comments. + if (line.empty() || line.front() == '#') { + continue; + } + + auto const kv_pairs = parse_legacy_line(line); + if (kv_pairs.empty()) { + continue; + } + + SSLMultiCertEntry entry; + + for (auto const &[key, value] : kv_pairs) { + if (key == KEY_SSL_CERT_NAME) { + entry.ssl_cert_name = value; + } else if (key == KEY_DEST_IP) { + entry.dest_ip = value; + } else if (key == KEY_SSL_KEY_NAME) { + entry.ssl_key_name = value; + } else if (key == KEY_SSL_CA_NAME) { + entry.ssl_ca_name = value; + } else if (key == KEY_SSL_OCSP_NAME) { + entry.ssl_ocsp_name = value; + } else if (key == KEY_SSL_KEY_DIALOG) { + entry.ssl_key_dialog = value; + } else if (key == KEY_DEST_FQDN) { + entry.dest_fqdn = value; + } else if (key == KEY_ACTION) { + entry.action = value; + } else if (key == KEY_SSL_TICKET_ENABLED) { + entry.ssl_ticket_enabled = swoc::svtoi(value); + } else if (key == KEY_SSL_TICKET_NUMBER) { + entry.ssl_ticket_number = swoc::svtoi(value); + } else if (unknown_keys.insert(key).second) { + errata.note(ERRATA_NOTE_SEV, "Ignoring unknown ssl_multicert key '{}' in legacy format", key); + } + } + + result.push_back(std::move(entry)); + } + + return {result, std::move(errata)}; +} + +std::string +SSLMultiCertMarshaller::to_yaml(SSLMultiCertConfig const &config) +{ + YAML::Emitter yaml; + yaml << YAML::BeginMap; + yaml << YAML::Key << KEY_SSL_MULTICERT << YAML::Value << YAML::BeginSeq; + + for (auto const &entry : config) { + emit_entry(yaml, entry); + } + + yaml << YAML::EndSeq << YAML::EndMap; + return yaml.c_str(); +} + +std::string +SSLMultiCertMarshaller::to_json(SSLMultiCertConfig const &config) +{ + YAML::Emitter json; + json << YAML::DoubleQuoted << YAML::Flow; + json << YAML::BeginMap; + json << YAML::Key << KEY_SSL_MULTICERT << YAML::Value << YAML::BeginSeq; + + for (auto const &entry : config) { + emit_entry(json, entry); + } + + json << YAML::EndSeq << YAML::EndMap; + return json.c_str(); +} + +} // namespace config diff --git a/src/config/unit_tests/test_ssl_multicert.cc b/src/config/unit_tests/test_ssl_multicert.cc new file mode 100644 index 00000000000..7baae9563bc --- /dev/null +++ b/src/config/unit_tests/test_ssl_multicert.cc @@ -0,0 +1,482 @@ +/** @file + + Unit tests for ssl_multicert configuration parsing and marshalling. + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "config/ssl_multicert.h" + +#include +#include + +#include +#include + +using namespace config; + +namespace +{ +// Helper to create a temporary file with content. +class TempFile +{ +public: + TempFile(std::string const &filename, std::string const &content) + { + _path = std::filesystem::temp_directory_path() / filename; + std::ofstream ofs(_path); + ofs << content; + } + + ~TempFile() { std::filesystem::remove(_path); } + + std::string + path() const + { + return _path.string(); + } + +private: + std::filesystem::path _path; +}; + +// Helper to parse content via temp file. +ConfigResult +parse_content(std::string const &content, std::string const &filename) +{ + TempFile file(filename, content); + SSLMultiCertParser parser; + return parser.parse(file.path()); +} +} // namespace + +// Sample legacy config content. +static constexpr char LEGACY_CONFIG[] = R"(# Comment line +ssl_cert_name=server.pem ssl_key_name=server.key dest_ip=* +ssl_cert_name=another.pem dest_ip="[::1]:8443" ssl_ticket_enabled=1 +ssl_cert_name=quoted.pem ssl_key_dialog="exec:/usr/bin/getpass arg1 'arg 2'" +)"; + +// Sample YAML config content. +static constexpr char YAML_CONFIG[] = R"(ssl_multicert: + - ssl_cert_name: server.pem + ssl_key_name: server.key + dest_ip: "*" + - ssl_cert_name: another.pem + dest_ip: "[::1]:8443" + ssl_ticket_enabled: 1 + - ssl_cert_name: quoted.pem + ssl_key_dialog: "exec:/usr/bin/getpass arg1 'arg 2'" +)"; + +TEST_CASE("SSLMultiCertParser parses legacy config format", "[ssl_multicert][parser][legacy]") +{ + auto result = parse_content(LEGACY_CONFIG, "ssl_multicert.config"); + + REQUIRE(result.ok()); + REQUIRE(result.value.size() == 3); + + SECTION("First entry") + { + auto const &entry = result.value[0]; + CHECK(entry.ssl_cert_name == "server.pem"); + CHECK(entry.ssl_key_name == "server.key"); + CHECK(entry.dest_ip == "*"); + CHECK_FALSE(entry.ssl_ticket_enabled.has_value()); + } + + SECTION("Second entry with IPv6 and ticket enabled") + { + auto const &entry = result.value[1]; + CHECK(entry.ssl_cert_name == "another.pem"); + CHECK(entry.dest_ip == "[::1]:8443"); + REQUIRE(entry.ssl_ticket_enabled.has_value()); + CHECK(entry.ssl_ticket_enabled.value() == 1); + } + + SECTION("Third entry with quoted dialog") + { + auto const &entry = result.value[2]; + CHECK(entry.ssl_cert_name == "quoted.pem"); + CHECK(entry.ssl_key_dialog == "exec:/usr/bin/getpass arg1 'arg 2'"); + } +} + +TEST_CASE("SSLMultiCertParser parses YAML config format", "[ssl_multicert][parser][yaml]") +{ + auto result = parse_content(YAML_CONFIG, "ssl_multicert.yaml"); + + REQUIRE(result.ok()); + REQUIRE(result.value.size() == 3); + + SECTION("First entry") + { + auto const &entry = result.value[0]; + CHECK(entry.ssl_cert_name == "server.pem"); + CHECK(entry.ssl_key_name == "server.key"); + CHECK(entry.dest_ip == "*"); + } + + SECTION("Second entry with IPv6 and ticket enabled") + { + auto const &entry = result.value[1]; + CHECK(entry.ssl_cert_name == "another.pem"); + CHECK(entry.dest_ip == "[::1]:8443"); + REQUIRE(entry.ssl_ticket_enabled.has_value()); + CHECK(entry.ssl_ticket_enabled.value() == 1); + } + + SECTION("Third entry with quoted dialog") + { + auto const &entry = result.value[2]; + CHECK(entry.ssl_cert_name == "quoted.pem"); + CHECK(entry.ssl_key_dialog == "exec:/usr/bin/getpass arg1 'arg 2'"); + } +} + +TEST_CASE("SSLMultiCertParser auto-detects format from filename", "[ssl_multicert][parser][detection]") +{ + auto [description, content, filename] = GENERATE(table({ + {"YAML from .yaml extension", YAML_CONFIG, "config.yaml" }, + {"YAML from .yml extension", YAML_CONFIG, "config.yml" }, + {"legacy from .config extension", LEGACY_CONFIG, "ssl_multicert.config"}, + {"YAML from content (no extension)", YAML_CONFIG, "config" }, + {"legacy from content (no extension)", LEGACY_CONFIG, "config" }, + })); + + CAPTURE(description, filename); + + auto result = parse_content(content, filename); + REQUIRE(result.ok()); + CHECK(result.value.size() == 3); +} + +TEST_CASE("SSLMultiCertParser returns empty config for empty input", "[ssl_multicert][parser][edge]") +{ + auto [description, content, filename] = GENERATE(table({ + {"empty YAML content", "", "config.yaml" }, + {"empty legacy content", "", "config.config"}, + {"comments only in legacy", "# Just a comment\n# Another comment\n", "config.config"}, + {"whitespace only", " \n\t\n ", "config.config"}, + {"empty ssl_multicert in YAML", "ssl_multicert: []\n", "config.yaml" }, + })); + + CAPTURE(description); + + auto result = parse_content(content, filename); + REQUIRE(result.ok()); + CHECK(result.value.empty()); +} + +TEST_CASE("SSLMultiCertParser returns error for invalid input", "[ssl_multicert][parser][edge]") +{ + auto [description, content, filename] = GENERATE(table({ + {"invalid YAML syntax", "ssl_multicert: [not: valid: yaml", "config.yaml"}, + {"missing ssl_multicert key", "other_key:\n - value: 1\n", "config.yaml"}, + })); + + CAPTURE(description); + + auto result = parse_content(content, filename); + CHECK_FALSE(result.ok()); +} + +TEST_CASE("SSLMultiCertParser handles all YAML entry fields", "[ssl_multicert][parser][fields]") +{ + static constexpr char FULL_YAML[] = R"(ssl_multicert: + - ssl_cert_name: cert.pem + dest_ip: "192.168.1.1" + ssl_key_name: key.pem + ssl_ca_name: ca.pem + ssl_ocsp_name: ocsp.der + ssl_key_dialog: "builtin" + dest_fqdn: "example.com" + action: tunnel + ssl_ticket_enabled: 1 + ssl_ticket_number: 5 +)"; + + auto result = parse_content(FULL_YAML, "config.yaml"); + REQUIRE(result.ok()); + REQUIRE(result.value.size() == 1); + + auto const &entry = result.value[0]; + CHECK(entry.ssl_cert_name == "cert.pem"); + CHECK(entry.dest_ip == "192.168.1.1"); + CHECK(entry.ssl_key_name == "key.pem"); + CHECK(entry.ssl_ca_name == "ca.pem"); + CHECK(entry.ssl_ocsp_name == "ocsp.der"); + CHECK(entry.ssl_key_dialog == "builtin"); + CHECK(entry.dest_fqdn == "example.com"); + CHECK(entry.action == "tunnel"); + REQUIRE(entry.ssl_ticket_enabled.has_value()); + CHECK(entry.ssl_ticket_enabled.value() == 1); + REQUIRE(entry.ssl_ticket_number.has_value()); + CHECK(entry.ssl_ticket_number.value() == 5); +} + +TEST_CASE("SSLMultiCertMarshaller produces valid YAML", "[ssl_multicert][marshaller][yaml]") +{ + SSLMultiCertConfig config; + + SSLMultiCertEntry entry1; + entry1.ssl_cert_name = "server.pem"; + entry1.dest_ip = "*"; + entry1.ssl_key_name = "server.key"; + config.push_back(entry1); + + SSLMultiCertEntry entry2; + entry2.ssl_cert_name = "another.pem"; + entry2.dest_ip = "[::1]:8443"; + entry2.ssl_ticket_enabled = 1; + config.push_back(entry2); + + SSLMultiCertMarshaller marshaller; + std::string yaml = marshaller.to_yaml(config); + + SECTION("YAML contains expected structure") + { + CHECK(yaml.find("ssl_multicert:") != std::string::npos); + CHECK(yaml.find("ssl_cert_name: server.pem") != std::string::npos); + CHECK(yaml.find("ssl_key_name: server.key") != std::string::npos); + CHECK(yaml.find("ssl_cert_name: another.pem") != std::string::npos); + CHECK(yaml.find("ssl_ticket_enabled: 1") != std::string::npos); + } + + SECTION("YAML can be re-parsed") + { + auto result = parse_content(yaml, "config.yaml"); + REQUIRE(result.ok()); + REQUIRE(result.value.size() == 2); + CHECK(result.value[0].ssl_cert_name == "server.pem"); + CHECK(result.value[1].ssl_cert_name == "another.pem"); + } +} + +TEST_CASE("SSLMultiCertMarshaller produces valid JSON", "[ssl_multicert][marshaller][json]") +{ + SSLMultiCertConfig config; + + SSLMultiCertEntry entry1; + entry1.ssl_cert_name = "server.pem"; + entry1.dest_ip = "*"; + config.push_back(entry1); + + SSLMultiCertEntry entry2; + entry2.ssl_cert_name = "another.pem"; + entry2.dest_ip = "[::1]:8443"; + entry2.ssl_ticket_enabled = 1; + entry2.ssl_ticket_number = 5; + config.push_back(entry2); + + SSLMultiCertMarshaller marshaller; + std::string json = marshaller.to_json(config); + + CHECK(json.find("\"ssl_multicert\"") != std::string::npos); + CHECK(json.find("\"ssl_cert_name\": \"server.pem\"") != std::string::npos); + CHECK(json.find("\"ssl_cert_name\": \"another.pem\"") != std::string::npos); + CHECK(json.find("\"ssl_ticket_enabled\": 1") != std::string::npos); + CHECK(json.find("\"ssl_ticket_number\": 5") != std::string::npos); + CHECK(json.find('[') != std::string::npos); + CHECK(json.find(']') != std::string::npos); +} + +TEST_CASE("SSLMultiCertMarshaller handles special characters", "[ssl_multicert][marshaller][escaping]") +{ + SSLMultiCertConfig config; + + SSLMultiCertEntry entry; + entry.ssl_cert_name = "server.pem"; + entry.dest_ip = "*"; + entry.ssl_key_dialog = "exec:/path/to/script \"with quotes\""; + config.push_back(entry); + + SSLMultiCertMarshaller marshaller; + + SECTION("YAML output contains the field and can be re-parsed") + { + std::string yaml = marshaller.to_yaml(config); + CHECK(yaml.find("ssl_key_dialog:") != std::string::npos); + + // Verify round-trip preserves the value. + auto result = parse_content(yaml, "test.yaml"); + REQUIRE(result.ok()); + REQUIRE(result.value.size() == 1); + CHECK(result.value[0].ssl_key_dialog == "exec:/path/to/script \"with quotes\""); + } + + SECTION("JSON escapes quotes") + { + std::string json = marshaller.to_json(config); + CHECK(json.find("\\\"with quotes\\\"") != std::string::npos); + } +} + +TEST_CASE("Round-trip: legacy -> parse -> yaml -> parse", "[ssl_multicert][roundtrip]") +{ + SSLMultiCertMarshaller marshaller; + + // Parse legacy format. + auto legacy_result = parse_content(LEGACY_CONFIG, "ssl_multicert.config"); + REQUIRE(legacy_result.ok()); + + // Marshal to YAML. + std::string yaml = marshaller.to_yaml(legacy_result.value); + + // Re-parse YAML. + auto yaml_result = parse_content(yaml, "ssl_multicert.yaml"); + REQUIRE(yaml_result.ok()); + + // Verify same number of entries. + REQUIRE(legacy_result.value.size() == yaml_result.value.size()); + + // Verify entries match. + for (size_t i = 0; i < legacy_result.value.size(); ++i) { + CHECK(legacy_result.value[i].ssl_cert_name == yaml_result.value[i].ssl_cert_name); + CHECK(legacy_result.value[i].ssl_key_name == yaml_result.value[i].ssl_key_name); + CHECK(legacy_result.value[i].ssl_key_dialog == yaml_result.value[i].ssl_key_dialog); + } +} + +TEST_CASE("SSLMultiCertParser::parse returns error for missing file", "[ssl_multicert][parser][file]") +{ + SSLMultiCertParser parser; + + auto result = parser.parse("/nonexistent/path/to/ssl_multicert.yaml"); + CHECK_FALSE(result.ok()); +} + +// ============================================================================ +// Legacy format edge cases (parameterized) +// ============================================================================ + +TEST_CASE("Legacy parser handles whitespace variations", "[ssl_multicert][parser][legacy][whitespace]") +{ + auto [description, config, expected_cert, expected_key] = GENERATE(table({ + {"multiple spaces between pairs", "ssl_cert_name=a.pem ssl_key_name=a.key", "a.pem", "a.key"}, + {"tabs between pairs", "ssl_cert_name=a.pem\tssl_key_name=a.key", "a.pem", "a.key"}, + {"leading whitespace", " ssl_cert_name=a.pem ssl_key_name=a.key", "a.pem", "a.key"}, + {"trailing whitespace", "ssl_cert_name=a.pem ssl_key_name=a.key ", "a.pem", "a.key"}, + {"leading tabs", "\t\tssl_cert_name=a.pem ssl_key_name=a.key", "a.pem", "a.key"}, + {"mixed leading whitespace", " \t ssl_cert_name=a.pem ssl_key_name=a.key", "a.pem", "a.key"}, + })); + + CAPTURE(description, config); + + auto result = parse_content(config, "test.config"); + REQUIRE(result.ok()); + REQUIRE(result.value.size() == 1); + CHECK(result.value[0].ssl_cert_name == expected_cert); + CHECK(result.value[0].ssl_key_name == expected_key); +} + +TEST_CASE("Legacy parser handles quoted values", "[ssl_multicert][parser][legacy][quotes]") +{ + auto [description, config, expected_field, expected_value] = + GENERATE(table({ + {"double-quoted with spaces", R"(ssl_cert_name="path with spaces.pem")", "ssl_cert_name", "path with spaces.pem"}, + {"single-quoted with spaces", R"(ssl_cert_name='path with spaces.pem')", "ssl_cert_name", "path with spaces.pem"}, + {"quoted followed by unquoted", R"(ssl_key_dialog="exec:/bin/script arg" ssl_cert_name=c.pem)", "ssl_key_dialog", + "exec:/bin/script arg" }, + {"IPv6 in quotes", R"(dest_ip="[::1]:443" ssl_cert_name=cert.pem)", "dest_ip", "[::1]:443" }, + {"equals inside quotes", R"(ssl_cert_name="value=with=equals")", "ssl_cert_name", "value=with=equals" }, + })); + + CAPTURE(description, config); + + auto result = parse_content(config, "test.config"); + REQUIRE(result.ok()); + REQUIRE(result.value.size() == 1); + + auto const &entry = result.value[0]; + if (expected_field == std::string("ssl_cert_name")) { + CHECK(entry.ssl_cert_name == expected_value); + } else if (expected_field == std::string("ssl_key_dialog")) { + CHECK(entry.ssl_key_dialog == expected_value); + } else if (expected_field == std::string("dest_ip")) { + CHECK(entry.dest_ip == expected_value); + } +} + +TEST_CASE("Legacy parser handles multiline content", "[ssl_multicert][parser][legacy][multiline]") +{ + auto [description, config, expected_count] = GENERATE(table({ + {"three entries", "ssl_cert_name=first.pem\nssl_cert_name=second.pem\nssl_cert_name=third.pem", 3}, + {"with comments and blanks", "# Header\nssl_cert_name=first.pem\n\n# Comment\nssl_cert_name=second.pem\n", 2}, + {"Windows CRLF line endings", "ssl_cert_name=first.pem\r\nssl_cert_name=second.pem\r\n", 2}, + {"single line no newline", "ssl_cert_name=only.pem", 1}, + {"single line with newline", "ssl_cert_name=only.pem\n", 1}, + })); + + CAPTURE(description); + + auto result = parse_content(config, "test.config"); + REQUIRE(result.ok()); + CHECK(result.value.size() == expected_count); +} + +TEST_CASE("Legacy parser handles all field types", "[ssl_multicert][parser][legacy][fields]") +{ + static constexpr char FULL_LEGACY[] = "ssl_cert_name=cert.pem dest_ip=192.168.1.1 ssl_key_name=key.pem ssl_ca_name=ca.pem " + "ssl_ocsp_name=ocsp.der ssl_key_dialog=builtin dest_fqdn=example.com action=tunnel " + "ssl_ticket_enabled=1 ssl_ticket_number=5"; + + auto result = parse_content(FULL_LEGACY, "test.config"); + REQUIRE(result.ok()); + REQUIRE(result.value.size() == 1); + + auto const &entry = result.value[0]; + CHECK(entry.ssl_cert_name == "cert.pem"); + CHECK(entry.dest_ip == "192.168.1.1"); + CHECK(entry.ssl_key_name == "key.pem"); + CHECK(entry.ssl_ca_name == "ca.pem"); + CHECK(entry.ssl_ocsp_name == "ocsp.der"); + CHECK(entry.ssl_key_dialog == "builtin"); + CHECK(entry.dest_fqdn == "example.com"); + CHECK(entry.action == "tunnel"); + REQUIRE(entry.ssl_ticket_enabled.has_value()); + CHECK(entry.ssl_ticket_enabled.value() == 1); + REQUIRE(entry.ssl_ticket_number.has_value()); + CHECK(entry.ssl_ticket_number.value() == 5); +} + +TEST_CASE("Legacy parser handles dual certificates", "[ssl_multicert][parser][legacy][dual-cert]") +{ + auto result = + parse_content("ssl_cert_name=server-ec.pem,server-rsa.pem ssl_key_name=server-ec.key,server-rsa.key", "test.config"); + REQUIRE(result.ok()); + REQUIRE(result.value.size() == 1); + CHECK(result.value[0].ssl_cert_name == "server-ec.pem,server-rsa.pem"); + CHECK(result.value[0].ssl_key_name == "server-ec.key,server-rsa.key"); +} + +TEST_CASE("Legacy parser skips malformed entries", "[ssl_multicert][parser][legacy][malformed]") +{ + auto [description, config, expected_count] = GENERATE(table({ + {"line without equals", "ssl_cert_name=valid.pem\nmalformed_no_equals\nssl_cert_name=another.pem", 2}, + {"blank line between entries", "ssl_cert_name=first.pem\n\nssl_cert_name=second.pem", 2}, + {"comment before valid entry", "# only comment\nssl_cert_name=valid.pem", 1}, + })); + + CAPTURE(description); + + auto result = parse_content(config, "test.config"); + REQUIRE(result.ok()); + CHECK(result.value.size() == expected_count); +} diff --git a/src/iocore/net/CMakeLists.txt b/src/iocore/net/CMakeLists.txt index a416ec18fe2..16563e10ab1 100644 --- a/src/iocore/net/CMakeLists.txt +++ b/src/iocore/net/CMakeLists.txt @@ -108,7 +108,7 @@ target_link_libraries( OpenSSL::Crypto OpenSSL::SSL ts::tsapibackend - PRIVATE ts::tsutil yaml-cpp::yaml-cpp + PRIVATE ts::config ts::tsutil yaml-cpp::yaml-cpp ) # Is this necessary? diff --git a/src/iocore/net/P_SSLCertLookup.h b/src/iocore/net/P_SSLCertLookup.h index da31f58086d..b40baa74c30 100644 --- a/src/iocore/net/P_SSLCertLookup.h +++ b/src/iocore/net/P_SSLCertLookup.h @@ -46,7 +46,7 @@ enum class SSLCertContextOption { }; /** - @brief Gather user provided settings from ssl_multicert.config in to this single struct + @brief Gather user provided settings from ssl_multicert.yaml in to this single struct */ struct SSLMultiCertConfigParams { SSLMultiCertConfigParams() : opt(SSLCertContextOption::OPT_NONE) diff --git a/src/iocore/net/SSLUtils.cc b/src/iocore/net/SSLUtils.cc index 911d63d4480..b5bcfe9d81c 100644 --- a/src/iocore/net/SSLUtils.cc +++ b/src/iocore/net/SSLUtils.cc @@ -32,6 +32,7 @@ #include "SSLDynlock.h" // IWYU pragma: keep - for ssl_dyn_* #include "iocore/net/SSLMultiCertConfigLoader.h" +#include "config/ssl_multicert.h" #include "iocore/net/SSLAPIHooks.h" #include "iocore/net/SSLDiags.h" #include "iocore/net/TLSSessionResumptionSupport.h" @@ -74,19 +75,7 @@ using namespace std::literals; -// ssl_multicert.config field names: -static constexpr std::string_view SSL_IP_TAG("dest_ip"sv); -static constexpr std::string_view SSL_CERT_TAG("ssl_cert_name"sv); -static constexpr std::string_view SSL_PRIVATE_KEY_TAG("ssl_key_name"sv); -static constexpr std::string_view SSL_OCSP_RESPONSE_TAG("ssl_ocsp_name"sv); -static constexpr std::string_view SSL_CA_TAG("ssl_ca_name"sv); -static constexpr std::string_view SSL_ACTION_TAG("action"sv); -static constexpr std::string_view SSL_ACTION_TUNNEL_TAG("tunnel"sv); -static constexpr std::string_view SSL_SESSION_TICKET_ENABLED("ssl_ticket_enabled"sv); -static constexpr std::string_view SSL_SESSION_TICKET_NUMBER("ssl_ticket_number"sv); -static constexpr std::string_view SSL_KEY_DIALOG("ssl_key_dialog"sv); -static constexpr std::string_view SSL_SERVERNAME("dest_fqdn"sv); -static constexpr char SSL_CERT_SEPARATE_DELIM = ','; +static constexpr char SSL_CERT_SEPARATE_DELIM = ','; #ifndef evp_md_func #ifdef OPENSSL_NO_SHA256 @@ -1283,7 +1272,7 @@ SSLMultiCertConfigLoader::_setup_dialog(SSL_CTX *ctx, const SSLMultiCertConfigPa } else if (strcmp(sslMultCertSettings->dialog, "builtin") == 0) { passwd_cb = ssl_private_key_passphrase_callback_builtin; } else { // unknown config - SSLError("unknown %s configuration value '%s'", SSL_KEY_DIALOG.data(), (const char *)sslMultCertSettings->dialog); + SSLError("unknown ssl_key_dialog configuration value '%s'", (const char *)sslMultCertSettings->dialog); return false; } SSL_CTX_set_default_passwd_cb(ctx, passwd_cb); @@ -1299,7 +1288,7 @@ SSLMultiCertConfigLoader::_set_verify_path(SSL_CTX *ctx, const SSLMultiCertConfi // serverCACertFilename if that is not nullptr. Otherwise, it uses the hashed // symlinks in serverCACertPath. // - // if ssl_ca_name is NOT configured for this cert in ssl_multicert.config + // if ssl_ca_name is NOT configured for this cert in ssl_multicert.yaml // AND // if proxy.config.ssl.CA.cert.filename and proxy.config.ssl.CA.cert.path // are configured @@ -1719,144 +1708,76 @@ SSLMultiCertConfigLoader::_store_single_ssl_ctx(SSLCertLookup *lookup, const sha return ctx.get(); } -static bool -ssl_extract_certificate(const matcher_line *line_info, SSLMultiCertConfigParams *sslMultCertSettings) +swoc::Errata +SSLMultiCertConfigLoader::load(SSLCertLookup *lookup) { - for (int i = 0; i < MATCHER_MAX_TOKENS; ++i) { - const char *label; - const char *value; + const SSLConfigParams *params = this->_params; - label = line_info->line[0][i]; - value = line_info->line[1][i]; + Note("(%s) %s loading ...", this->_debug_tag(), ts::filename::SSL_MULTICERT); - if (label == nullptr) { - continue; - } - Dbg(dbg_ctl_ssl_load, "Extracting certificate label: %s, value: %s", label, value); + // Optionally elevate/allow file access to read root-only + // certificates. The destructor will drop privilege for us. + uint32_t elevate_setting = 0; + elevate_setting = RecGetRecordInt("proxy.config.ssl.cert.load_elevated").value_or(0); + ElevateAccess elevate_access(elevate_setting ? ElevateAccess::FILE_PRIVILEGE : 0); - if (strcasecmp(label, SSL_IP_TAG) == 0) { - sslMultCertSettings->addr = ats_strdup(value); - } + // Guard against nullptr configFilePath which can happen if records aren't initialized. + if (params->configFilePath == nullptr) { + return swoc::Errata(ERRATA_WARN, "No SSL certificate configuration file path configured"); + } - if (strcasecmp(label, SSL_CERT_TAG) == 0) { - sslMultCertSettings->cert = ats_strdup(value); - } + config::SSLMultiCertParser parser; + config::ConfigResult parse_result = parser.parse(params->configFilePath); + if (!parse_result.ok()) { + return std::move(parse_result.errata); + } - if (strcasecmp(label, SSL_CA_TAG) == 0) { - sslMultCertSettings->ca = ats_strdup(value); - } + swoc::Errata errata(ERRATA_NOTE); + int item_num = 0; - if (strcasecmp(label, SSL_PRIVATE_KEY_TAG) == 0) { - sslMultCertSettings->key = ats_strdup(value); - } + for (const auto &item : parse_result.value) { + item_num++; + shared_SSLMultiCertConfigParams sslMultiCertSettings = std::make_shared(); - if (strcasecmp(label, SSL_OCSP_RESPONSE_TAG) == 0) { - sslMultCertSettings->ocsp_response = ats_strdup(value); + if (!item.ssl_cert_name.empty()) { + sslMultiCertSettings->cert = ats_strdup(item.ssl_cert_name.c_str()); } - - if (strcasecmp(label, SSL_SESSION_TICKET_ENABLED) == 0) { - sslMultCertSettings->session_ticket_enabled = atoi(value); + if (!item.dest_ip.empty()) { + sslMultiCertSettings->addr = ats_strdup(item.dest_ip.c_str()); } - - if (strcasecmp(label, SSL_SESSION_TICKET_NUMBER) == 0) { - sslMultCertSettings->session_ticket_number = atoi(value); + if (!item.ssl_key_name.empty()) { + sslMultiCertSettings->key = ats_strdup(item.ssl_key_name.c_str()); } - - if (strcasecmp(label, SSL_KEY_DIALOG) == 0) { - sslMultCertSettings->dialog = ats_strdup(value); + if (!item.ssl_ca_name.empty()) { + sslMultiCertSettings->ca = ats_strdup(item.ssl_ca_name.c_str()); } - - if (strcasecmp(label, SSL_SERVERNAME) == 0) { - sslMultCertSettings->servername = ats_strdup(value); + if (!item.ssl_ocsp_name.empty()) { + sslMultiCertSettings->ocsp_response = ats_strdup(item.ssl_ocsp_name.c_str()); } - - if (strcasecmp(label, SSL_ACTION_TAG) == 0) { - if (strcasecmp(SSL_ACTION_TUNNEL_TAG, value) == 0) { - sslMultCertSettings->opt = SSLCertContextOption::OPT_TUNNEL; - } else { - Error("Unrecognized action for %s", SSL_ACTION_TAG.data()); - return false; - } + if (!item.ssl_key_dialog.empty()) { + sslMultiCertSettings->dialog = ats_strdup(item.ssl_key_dialog.c_str()); } - } - // TS-4679: It is ok to be missing the cert. At least if the action is set to tunnel - if (sslMultCertSettings->cert) { - SimpleTokenizer cert_tok(sslMultCertSettings->cert, SSL_CERT_SEPARATE_DELIM); - const char *first_cert = cert_tok.getNext(); - if (first_cert) { - sslMultCertSettings->first_cert = ats_strdup(first_cert); + if (!item.dest_fqdn.empty()) { + sslMultiCertSettings->servername = ats_strdup(item.dest_fqdn.c_str()); } - } - - return true; -} - -swoc::Errata -SSLMultiCertConfigLoader::load(SSLCertLookup *lookup) -{ - const SSLConfigParams *params = this->_params; - - char *tok_state = nullptr; - char *line = nullptr; - unsigned line_num = 0; - matcher_line line_info; - - const matcher_tags sslCertTags = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, false}; - - Note("(%s) %s loading ...", this->_debug_tag(), ts::filename::SSL_MULTICERT); - - std::error_code ec; - std::string content{swoc::file::load(swoc::file::path{params->configFilePath}, ec)}; - if (ec) { - switch (ec.value()) { - case ENOENT: - // missing config file is an acceptable runtime state - return swoc::Errata(ERRATA_WARN, "Cannot open SSL certificate configuration \"{}\" - {}", params->configFilePath, ec); - default: - return swoc::Errata(ERRATA_ERROR, "Failed to read SSL certificate configuration from \"{}\" - {}", params->configFilePath, - ec); + if (item.ssl_ticket_enabled.has_value()) { + sslMultiCertSettings->session_ticket_enabled = item.ssl_ticket_enabled.value(); } - } - - // Optionally elevate/allow file access to read root-only - // certificates. The destructor will drop privilege for us. - uint32_t elevate_setting = 0; - elevate_setting = RecGetRecordInt("proxy.config.ssl.cert.load_elevated").value_or(0); - ElevateAccess elevate_access(elevate_setting ? ElevateAccess::FILE_PRIVILEGE : 0); - - line = tokLine(content.data(), &tok_state); - swoc::Errata errata(ERRATA_NOTE); - while (line != nullptr) { - line_num++; - - // Skip all blank spaces at beginning of line. - while (*line && isspace(*line)) { - line++; + if (item.ssl_ticket_number.has_value()) { + sslMultiCertSettings->session_ticket_number = item.ssl_ticket_number.value(); + } + if (item.action == "tunnel") { + sslMultiCertSettings->opt = SSLCertContextOption::OPT_TUNNEL; } - if (*line != '\0' && *line != '#') { - shared_SSLMultiCertConfigParams sslMultiCertSettings = std::make_shared(); - const char *errPtr; - - errPtr = parseConfigLine(line, &line_info, &sslCertTags); - Dbg(dbg_ctl_ssl_load, "currently parsing %s at line %d from config file: %s", line, line_num, params->configFilePath); - if (errPtr != nullptr) { - Warning("%s: discarding %s entry at line %d: %s", __func__, params->configFilePath, line_num, errPtr); - } else { - if (ssl_extract_certificate(&line_info, sslMultiCertSettings.get())) { - // There must be a certificate specified unless the tunnel action is set - if (sslMultiCertSettings->cert || sslMultiCertSettings->opt != SSLCertContextOption::OPT_TUNNEL) { - if (!this->_store_ssl_ctx(lookup, sslMultiCertSettings)) { - errata.note(ERRATA_ERROR, "Failed to load certificate on line {}", line_num); - } - } else { - errata.note(ERRATA_WARN, "No ssl_cert_name specified and no tunnel action set on line {}", line_num); - } - } + // There must be a certificate specified unless the tunnel action is set. + if (sslMultiCertSettings->cert || sslMultiCertSettings->opt == SSLCertContextOption::OPT_TUNNEL) { + if (!this->_store_ssl_ctx(lookup, sslMultiCertSettings)) { + errata.note(ERRATA_ERROR, "Failed to load certificate at item {}", item_num); } + } else { + errata.note(ERRATA_WARN, "No ssl_cert_name specified and no tunnel action set at item {}", item_num); } - - line = tokLine(nullptr, &tok_state); } // We *must* have a default context even if it can't possibly work. The default context is used to diff --git a/src/traffic_ctl/CMakeLists.txt b/src/traffic_ctl/CMakeLists.txt index 671789b852b..c967d42e9c9 100644 --- a/src/traffic_ctl/CMakeLists.txt +++ b/src/traffic_ctl/CMakeLists.txt @@ -16,11 +16,18 @@ ####################### add_executable( - traffic_ctl traffic_ctl.cc CtrlCommands.cc CtrlPrinters.cc FileConfigCommand.cc PrintUtils.cc - ${CMAKE_SOURCE_DIR}/src/shared/rpc/IPCSocketClient.cc + traffic_ctl + traffic_ctl.cc + ConvertConfigCommand.cc + CtrlCommands.cc + CtrlPrinters.cc + FileConfigCommand.cc + PrintUtils.cc + SSLMultiCertCommand.cc + ${CMAKE_SOURCE_DIR}/src/shared/rpc/IPCSocketClient.cc ) -target_link_libraries(traffic_ctl ts::tscore libswoc::libswoc yaml-cpp::yaml-cpp ts::tsutil) +target_link_libraries(traffic_ctl ts::tscore ts::config libswoc::libswoc yaml-cpp::yaml-cpp ts::tsutil) install(TARGETS traffic_ctl) diff --git a/src/traffic_ctl/ConvertConfigCommand.cc b/src/traffic_ctl/ConvertConfigCommand.cc new file mode 100644 index 00000000000..b387673698a --- /dev/null +++ b/src/traffic_ctl/ConvertConfigCommand.cc @@ -0,0 +1,80 @@ +/** @file + + Configuration format conversion command for traffic_ctl. + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "ConvertConfigCommand.h" +#include "config/ssl_multicert.h" + +#include +#include + +ConvertConfigCommand::ConvertConfigCommand(ts::Arguments *args) : CtrlCommand(args) +{ + BasePrinter::Options print_opts{parse_print_opts(args)}; + _printer = std::make_unique(print_opts); + + if (args->get("ssl_multicert")) { + auto const &convert_args = args->get("ssl_multicert"); + if (convert_args.size() < 2) { + throw std::invalid_argument("ssl_multicert requires "); + } + _input_file = convert_args[0]; + _output_file = convert_args[1]; + _invoked_func = [this]() { convert_ssl_multicert(); }; + } else { + throw std::invalid_argument("Unsupported config type for conversion"); + } +} + +void +ConvertConfigCommand::convert_ssl_multicert() +{ + config::SSLMultiCertParser parser; + config::ConfigResult result = parser.parse(_input_file); + + if (!result.ok()) { + std::string error_msg = "Failed to parse input file '" + _input_file + "'"; + if (!result.errata.empty()) { + error_msg += ": "; + error_msg += std::string(result.errata.front().text()); + } + _printer->write_output(error_msg); + return; + } + + config::SSLMultiCertMarshaller marshaller; + std::string const yaml_output = marshaller.to_yaml(result.value); + + // Write to output file or stdout if output is "-". + if (_output_file == "-") { + std::cout << yaml_output << '\n'; + } else { + std::ofstream out(_output_file); + if (!out) { + _printer->write_output("Failed to open output file '" + _output_file + "' for writing"); + return; + } + out << yaml_output << '\n'; + out.close(); + _printer->write_output("Converted " + _input_file + " -> " + _output_file); + } +} diff --git a/src/traffic_ctl/ConvertConfigCommand.h b/src/traffic_ctl/ConvertConfigCommand.h new file mode 100644 index 00000000000..aee7e55fe09 --- /dev/null +++ b/src/traffic_ctl/ConvertConfigCommand.h @@ -0,0 +1,49 @@ +/** @file + + Configuration format conversion command for traffic_ctl. + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#pragma once + +#include "CtrlCommands.h" + +/** + * Command handler for configuration format conversion. + * + * Converts configuration files from legacy formats to YAML. + * Supports: ssl_multicert + */ +class ConvertConfigCommand : public CtrlCommand +{ +public: + /** + * Construct the command from parsed arguments. + * + * @param[in] args Parsed command line arguments. + */ + ConvertConfigCommand(ts::Arguments *args); + +private: + void convert_ssl_multicert(); + + std::string _input_file; + std::string _output_file; +}; diff --git a/src/traffic_ctl/SSLMultiCertCommand.cc b/src/traffic_ctl/SSLMultiCertCommand.cc new file mode 100644 index 00000000000..ebc5d00f357 --- /dev/null +++ b/src/traffic_ctl/SSLMultiCertCommand.cc @@ -0,0 +1,84 @@ +/** @file + + SSL Multi-Certificate configuration command for traffic_ctl. + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "SSLMultiCertCommand.h" +#include "config/ssl_multicert.h" +#include "tscore/Layout.h" +#include "tscore/Filenames.h" + +#include + +namespace +{ + +/// Get the default ssl_multicert.yaml file path. +std::string +get_default_ssl_multicert_path() +{ + std::string sysconfdir; + if (char const *env = getenv("PROXY_CONFIG_CONFIG_DIR")) { + sysconfdir = Layout::get()->relative(env); + } else { + sysconfdir = Layout::get()->sysconfdir; + } + return Layout::get()->relative_to(sysconfdir, ts::filename::SSL_MULTICERT); +} + +} // namespace + +SSLMultiCertCommand::SSLMultiCertCommand(ts::Arguments *args) : CtrlCommand(args) +{ + BasePrinter::Options print_opts{parse_print_opts(args)}; + _printer = std::make_unique(print_opts); + + if (args->get("show")) { + // Default to YAML; use JSON only if explicitly requested. + _output_json = args->get("json"); + _invoked_func = [this]() { show_config(); }; + } else { + throw std::invalid_argument("Unsupported ssl-multicert subcommand"); + } +} + +void +SSLMultiCertCommand::show_config() +{ + std::string const filename = get_default_ssl_multicert_path(); + + config::SSLMultiCertParser parser; + config::ConfigResult result = parser.parse(filename); + + if (!result.ok()) { + std::string error_msg = "Failed to parse ssl_multicert config"; + if (!result.errata.empty()) { + error_msg += ": "; + error_msg += std::string(result.errata.front().text()); + } + _printer->write_output(error_msg); + return; + } + + config::SSLMultiCertMarshaller marshaller; + std::string const output = _output_json ? marshaller.to_json(result.value) : marshaller.to_yaml(result.value); + _printer->write_output(output); +} diff --git a/src/traffic_ctl/SSLMultiCertCommand.h b/src/traffic_ctl/SSLMultiCertCommand.h new file mode 100644 index 00000000000..d796d1d5b2c --- /dev/null +++ b/src/traffic_ctl/SSLMultiCertCommand.h @@ -0,0 +1,47 @@ +/** @file + + SSL Multi-Certificate configuration command for traffic_ctl. + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#pragma once + +#include "CtrlCommands.h" + +/** + * Command handler for ssl-multicert configuration operations. + * + * Supports reading and displaying ssl_multicert configuration in JSON or YAML format. + */ +class SSLMultiCertCommand : public CtrlCommand +{ +public: + /** + * Construct the command from parsed arguments. + * + * @param[in] args Parsed command line arguments. + */ + SSLMultiCertCommand(ts::Arguments *args); + +private: + void show_config(); + + bool _output_json = false; +}; diff --git a/src/traffic_ctl/traffic_ctl.cc b/src/traffic_ctl/traffic_ctl.cc index a018304a3f7..f7fdfdd071e 100644 --- a/src/traffic_ctl/traffic_ctl.cc +++ b/src/traffic_ctl/traffic_ctl.cc @@ -31,7 +31,9 @@ #include "tscore/signals.h" #include "CtrlCommands.h" +#include "ConvertConfigCommand.h" #include "FileConfigCommand.h" +#include "SSLMultiCertCommand.h" #include "TrafficCtlStatus.h" // Define the global variable @@ -143,6 +145,25 @@ main([[maybe_unused]] int argc, const char **argv) config_command.add_command("registry", "Show configuration file registry", Command_Execute) .add_example_usage("traffic_ctl config registry"); + + // ssl-multicert subcommand + auto &ssl_multicert_command = + config_command.add_command("ssl-multicert", "Manage ssl_multicert configuration").require_commands(); + auto &ssl_multicert_show = ssl_multicert_command.add_command("show", "Show the ssl_multicert configuration", Command_Execute) + .add_example_usage("traffic_ctl config ssl-multicert show") + .add_example_usage("traffic_ctl config ssl-multicert show --yaml") + .add_example_usage("traffic_ctl config ssl-multicert show --json"); + ssl_multicert_show.add_mutex_group("format", false, "Output format"); + ssl_multicert_show.add_option_to_group("format", "--yaml", "-y", "Output in YAML format (default)"); + ssl_multicert_show.add_option_to_group("format", "--json", "-j", "Output in JSON format"); + + // convert subcommand - convert config files between formats + auto &convert_command = config_command.add_command("convert", "Convert configuration files to YAML format").require_commands(); + convert_command.add_command("ssl_multicert", "Convert ssl_multicert.config to ssl_multicert.yaml", "", 2, Command_Execute) + .add_example_usage("traffic_ctl config convert ssl_multicert ") + .add_example_usage("traffic_ctl config convert ssl_multicert ssl_multicert.config ssl_multicert.yaml") + .add_example_usage("traffic_ctl config convert ssl_multicert ssl_multicert.config - # output to stdout"); + // host commands host_command.add_command("status", "Get one or more host statuses", "", MORE_THAN_ZERO_ARG_N, Command_Execute) .add_example_usage("traffic_ctl host status HOST [HOST ...]"); @@ -223,6 +244,12 @@ main([[maybe_unused]] int argc, const char **argv) auto create_command = [](ts::Arguments &args) -> std::unique_ptr { if (args.get("config")) { + if (args.get("convert")) { + return std::make_unique(&args); + } + if (args.get("ssl-multicert")) { + return std::make_unique(&args); + } if (args.get("cold")) { return std::make_unique(&args); } diff --git a/tests/gold_tests/autest-site/traffic_replay.test.ext b/tests/gold_tests/autest-site/traffic_replay.test.ext index f173033560b..c276fb2e445 100644 --- a/tests/gold_tests/autest-site/traffic_replay.test.ext +++ b/tests/gold_tests/autest-site/traffic_replay.test.ext @@ -29,7 +29,13 @@ def Replay(obj, name, replay_dir, key=None, cert=None, conn_type='mixed', option ts.addSSLfile(os.path.join(obj.Variables["AtsTestToolsDir"], "microserver", "ssl", "server.pem")) ts.addSSLfile(os.path.join(obj.Variables["AtsTestToolsDir"], "microserver", "ssl", "server.crt")) - ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.pem') + ts.Disk.ssl_multicert_yaml.AddLines( + """ + ssl_multicert: + - ssl_cert_name: server.pem + ssl_key_name: server.pem + dest_ip: "*" + """.split("\n")) # MicroServer setup - NOTE: expand to multiple microserver in future? server = obj.MakeOriginServer("server", both=True, lookup_key='{%uuid}') diff --git a/tests/gold_tests/autest-site/trafficserver.test.ext b/tests/gold_tests/autest-site/trafficserver.test.ext index a41f8948ced..d15d505fafc 100755 --- a/tests/gold_tests/autest-site/trafficserver.test.ext +++ b/tests/gold_tests/autest-site/trafficserver.test.ext @@ -303,7 +303,7 @@ def MakeATSProcess( tmpname = os.path.join(config_dir, fname) p.Disk.File(tmpname, id=make_id(fname), typename="ats:config") - fname = "ssl_multicert.config" + fname = "ssl_multicert.yaml" tmpname = os.path.join(config_dir, fname) p.Disk.File(tmpname, id=make_id(fname), typename="ats:config") diff --git a/tests/gold_tests/bigobj/bigobj.test.py b/tests/gold_tests/bigobj/bigobj.test.py index 55bb5c7403d..790516b7844 100644 --- a/tests/gold_tests/bigobj/bigobj.test.py +++ b/tests/gold_tests/bigobj/bigobj.test.py @@ -41,7 +41,13 @@ 'proxy.config.url_remap.remap_required': 0 }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine(f'map https://localhost:{ts.Variables.ssl_port} http://localhost:{ts.Variables.port}') ts.Disk.remap_config.AddLine(f'map https://localhost:{ts.Variables.ssl_portv6} http://localhost:{ts.Variables.port}') @@ -120,7 +126,13 @@ def create_pushfile(): 'proxy.config.url_remap.remap_required': 0 }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine(f'map https://localhost:{ts.Variables.ssl_port} http://localhost:{ts.Variables.port}') ts.Disk.remap_config.AddLine(f'map https://localhost:{ts.Variables.ssl_portv6} http://localhost:{ts.Variables.port}') diff --git a/tests/gold_tests/cache/background_fill.test.py b/tests/gold_tests/cache/background_fill.test.py index 552add221da..c9f5024f520 100644 --- a/tests/gold_tests/cache/background_fill.test.py +++ b/tests/gold_tests/cache/background_fill.test.py @@ -50,7 +50,13 @@ def __setupTS(self, ts_names=['default']): self.ts[name] = Test.MakeATSProcess(name, select_ports=True, enable_tls=True, enable_cache=True) self.ts[name].addDefaultSSLFiles() - self.ts[name].Disk.ssl_multicert_config.AddLine("dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key") + self.ts[name].Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts[name].Disk.records_config.update( { diff --git a/tests/gold_tests/chunked_encoding/bad_chunked_encoding.test.py b/tests/gold_tests/chunked_encoding/bad_chunked_encoding.test.py index 80addcef0d4..7e405f75844 100644 --- a/tests/gold_tests/chunked_encoding/bad_chunked_encoding.test.py +++ b/tests/gold_tests/chunked_encoding/bad_chunked_encoding.test.py @@ -96,7 +96,13 @@ def setupTS(self): "proxy.config.ssl.server.private_key.path": f'{self.ts.Variables.SSLDir}', "proxy.config.ssl.client.verify.server.policy": 'PERMISSIVE', }) - self.ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts.Disk.remap_config.AddLine(f"map / http://127.0.0.1:{self.server.Variables.http_port}/",) def runChunkedTraffic(self): @@ -150,7 +156,13 @@ def setupTS(self): "proxy.config.ssl.server.private_key.path": f'{self.ts.Variables.SSLDir}', "proxy.config.ssl.client.verify.server.policy": 'PERMISSIVE', }) - self.ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts.Disk.remap_config.AddLine(f"map / http://127.0.0.1:{self.server.Variables.http_port}/",) self.ts.Disk.traffic_out.Content += Testers.ContainsExpression( "user agent post chunk decoding error", "Verify that ATS detected a problem parsing a chunk.") diff --git a/tests/gold_tests/chunked_encoding/chunked_encoding.test.py b/tests/gold_tests/chunked_encoding/chunked_encoding.test.py index ab47b5e12e5..1c24420f5cc 100644 --- a/tests/gold_tests/chunked_encoding/chunked_encoding.test.py +++ b/tests/gold_tests/chunked_encoding/chunked_encoding.test.py @@ -90,7 +90,13 @@ 'map https://www.anotherexample.com https://127.0.0.1:{0}'.format(server2.Variables.SSL_Port, ts.Variables.ssl_port)) ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(Test.Variables.upstream_port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # smuggle-client is built via `make`. Here we copy the built binary down to the # test directory so that the test runs in this file can use it. diff --git a/tests/gold_tests/chunked_encoding/chunked_encoding_disabled.test.py b/tests/gold_tests/chunked_encoding/chunked_encoding_disabled.test.py index 8b7dc7cfed7..f584b906335 100644 --- a/tests/gold_tests/chunked_encoding/chunked_encoding_disabled.test.py +++ b/tests/gold_tests/chunked_encoding/chunked_encoding_disabled.test.py @@ -44,7 +44,13 @@ def setupTS(self): # Never respond with chunked encoding. "proxy.config.http.chunking_enabled": 0, }) - self.ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts.Disk.remap_config.AddLines( [ f"map /for/http http://127.0.0.1:{self.server.Variables.http_port}/", diff --git a/tests/gold_tests/chunked_encoding/chunked_encoding_h2.test.py b/tests/gold_tests/chunked_encoding/chunked_encoding_h2.test.py index 004267c2d60..cbf63581782 100644 --- a/tests/gold_tests/chunked_encoding/chunked_encoding_h2.test.py +++ b/tests/gold_tests/chunked_encoding/chunked_encoding_h2.test.py @@ -56,7 +56,13 @@ ts.Disk.remap_config.AddLine('map /post-full http://127.0.0.1:{0}'.format(Test.Variables.upstream_port2)) ts.Disk.remap_config.AddLine('map /post-chunked http://127.0.0.1:{0}'.format(Test.Variables.upstream_port3)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Using netcat as a cheap origin server in case 1 so we can insert a delay in sending back the response. # Replaced microserver for cases 2 and 3 as well because I was getting python exceptions when running diff --git a/tests/gold_tests/client_connection/per_client_connection_max.test.py b/tests/gold_tests/client_connection/per_client_connection_max.test.py index aa887d0768b..4bec83d487b 100644 --- a/tests/gold_tests/client_connection/per_client_connection_max.test.py +++ b/tests/gold_tests/client_connection/per_client_connection_max.test.py @@ -125,7 +125,13 @@ def _configure_trafficserver(self) -> None: name = f'ts{self._process_counter}' self._ts = Test.MakeATSProcess(name, enable_cache=False, enable_tls=True) self._ts.addDefaultSSLFiles() - self._ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self._ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) if self._protocol == Protocol.HTTP: server_port = self._server.Variables.http_port scheme = 'http' diff --git a/tests/gold_tests/connect/connect.test.py b/tests/gold_tests/connect/connect.test.py index c1ff3a187df..3ea58219f1b 100644 --- a/tests/gold_tests/connect/connect.test.py +++ b/tests/gold_tests/connect/connect.test.py @@ -221,7 +221,13 @@ def setupTS(self): }) self.ts.addDefaultSSLFiles() - self.ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts.Disk.remap_config.AddLines([ f"map / http://127.0.0.1:{self.server.Variables.http_port}/", diff --git a/tests/gold_tests/continuations/double_h2.test.py b/tests/gold_tests/continuations/double_h2.test.py index cb81c2d83a7..8ff4fa0acfa 100644 --- a/tests/gold_tests/continuations/double_h2.test.py +++ b/tests/gold_tests/continuations/double_h2.test.py @@ -48,7 +48,13 @@ # add port and remap rule ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { diff --git a/tests/gold_tests/continuations/openclose_h2.test.py b/tests/gold_tests/continuations/openclose_h2.test.py index 8cbeb010553..987636e8845 100644 --- a/tests/gold_tests/continuations/openclose_h2.test.py +++ b/tests/gold_tests/continuations/openclose_h2.test.py @@ -59,7 +59,13 @@ }) ts.Disk.remap_config.AddLine('map https://oc.test:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) cmd = '-k --resolve oc.test:{0}:127.0.0.1 --http2 https://oc.test:{0}'.format(ts.Variables.ssl_port) numberOfRequests = 100 diff --git a/tests/gold_tests/continuations/session_id.test.py b/tests/gold_tests/continuations/session_id.test.py index 5c20d025587..a10e45b3c2c 100644 --- a/tests/gold_tests/continuations/session_id.test.py +++ b/tests/gold_tests/continuations/session_id.test.py @@ -53,7 +53,13 @@ ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # # Run some HTTP/1 traffic. diff --git a/tests/gold_tests/cripts/cripts.test.py b/tests/gold_tests/cripts/cripts.test.py index ce46154ee59..bffe3c4c872 100644 --- a/tests/gold_tests/cripts/cripts.test.py +++ b/tests/gold_tests/cripts/cripts.test.py @@ -50,7 +50,13 @@ def setUpTS(self): self.ts = Test.MakeATSProcess("ts_in", enable_tls=True, enable_cache=False, enable_cripts=True) self.ts.addDefaultSSLFiles() - self.ts.Disk.ssl_multicert_config.AddLine("dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key") + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts.Setup.Copy('files/basic.cript', self.ts.Variables.CONFIGDIR) diff --git a/tests/gold_tests/early_hints/early_hints.test.py b/tests/gold_tests/early_hints/early_hints.test.py index 84c7a760edf..0f646624692 100644 --- a/tests/gold_tests/early_hints/early_hints.test.py +++ b/tests/gold_tests/early_hints/early_hints.test.py @@ -91,7 +91,13 @@ def _configure_ts(self, tr: 'TestRun'): self._ts = ts ts.Disk.remap_config.AddLine(f'map / http://backend.server.com:{self._server.Variables.http_port}') ts.addDefaultSSLFiles() - ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { 'proxy.config.ssl.server.cert.path': ts.Variables.SSLDir, diff --git a/tests/gold_tests/forward_proxy/forward_proxy.test.py b/tests/gold_tests/forward_proxy/forward_proxy.test.py index 49dd714bed8..6566414aec8 100644 --- a/tests/gold_tests/forward_proxy/forward_proxy.test.py +++ b/tests/gold_tests/forward_proxy/forward_proxy.test.py @@ -59,7 +59,13 @@ def setupTS(self): self.ts = Test.MakeATSProcess(proc_name, enable_tls=True, enable_cache=False) ForwardProxyTest._ts_counter += 1 self.ts.addDefaultSSLFiles() - self.ts.Disk.ssl_multicert_config.AddLine("dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key") + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts.Disk.remap_config.AddLine(f"map / http://127.0.0.1:{self.server.Variables.http_port}/") self.ts.Disk.records_config.update( diff --git a/tests/gold_tests/h2/grpc/grpc.test.py b/tests/gold_tests/h2/grpc/grpc.test.py index 72c52498102..4c0c19fe97c 100644 --- a/tests/gold_tests/h2/grpc/grpc.test.py +++ b/tests/gold_tests/h2/grpc/grpc.test.py @@ -53,7 +53,13 @@ def _configure_traffic_server(self, tr: 'TestRun', dns_port: int, server_port: i self._ts = tr.MakeATSProcess("ts", enable_tls=True, enable_cache=False) self._ts.addDefaultSSLFiles() - self._ts.Disk.ssl_multicert_config.AddLine("dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key") + self._ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self._ts.Disk.remap_config.AddLine(f"map / https://example.com:{server_port}/") diff --git a/tests/gold_tests/h2/h2disable.test.py b/tests/gold_tests/h2/h2disable.test.py index 9e645419e08..7946228fabc 100644 --- a/tests/gold_tests/h2/h2disable.test.py +++ b/tests/gold_tests/h2/h2disable.test.py @@ -35,7 +35,13 @@ ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/h2/h2disable_no_accept_threads.test.py b/tests/gold_tests/h2/h2disable_no_accept_threads.test.py index 3fc0a1d5020..e431858b908 100644 --- a/tests/gold_tests/h2/h2disable_no_accept_threads.test.py +++ b/tests/gold_tests/h2/h2disable_no_accept_threads.test.py @@ -35,7 +35,13 @@ ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/h2/h2enable.test.py b/tests/gold_tests/h2/h2enable.test.py index 36eb2fc7618..1aaf0168555 100644 --- a/tests/gold_tests/h2/h2enable.test.py +++ b/tests/gold_tests/h2/h2enable.test.py @@ -35,7 +35,13 @@ ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Set up port 4444 with HTTP1 only, no HTTP/2 ts.Disk.records_config.update( diff --git a/tests/gold_tests/h2/h2enable_no_accept_threads.test.py b/tests/gold_tests/h2/h2enable_no_accept_threads.test.py index c07aceec66b..c6818be4a4d 100644 --- a/tests/gold_tests/h2/h2enable_no_accept_threads.test.py +++ b/tests/gold_tests/h2/h2enable_no_accept_threads.test.py @@ -35,7 +35,13 @@ ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Set up port 4444 with HTTP1 only, no HTTP/2 ts.Disk.records_config.update( diff --git a/tests/gold_tests/h2/h2get_with_body.test.py b/tests/gold_tests/h2/h2get_with_body.test.py index f97aa04b996..89661b6362f 100644 --- a/tests/gold_tests/h2/h2get_with_body.test.py +++ b/tests/gold_tests/h2/h2get_with_body.test.py @@ -29,7 +29,13 @@ ts = Test.MakeATSProcess('ts', select_ports=True, enable_tls=True, enable_cache=True) ts.addDefaultSSLFiles() -ts.Disk.ssl_multicert_config.AddLine("dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key") +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { "proxy.config.http.server_ports": f"{ts.Variables.port} {ts.Variables.ssl_port}:ssl", diff --git a/tests/gold_tests/h2/h2origin.test.py b/tests/gold_tests/h2/h2origin.test.py index 24e92b553e9..6b0211a8d00 100644 --- a/tests/gold_tests/h2/h2origin.test.py +++ b/tests/gold_tests/h2/h2origin.test.py @@ -51,7 +51,13 @@ ts.Disk.remap_config.AddLines( [f'map /expect http://127.0.0.1:{server_expect.Variables.http_port}', f'map / https://127.0.0.1:{server.Variables.https_port}']) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.logging_yaml.AddLines( ''' diff --git a/tests/gold_tests/h2/h2origin_single_thread.test.py b/tests/gold_tests/h2/h2origin_single_thread.test.py index d8d5e468570..ba0b3389537 100644 --- a/tests/gold_tests/h2/h2origin_single_thread.test.py +++ b/tests/gold_tests/h2/h2origin_single_thread.test.py @@ -49,7 +49,13 @@ }) ts.Disk.remap_config.AddLine('map / https://127.0.0.1:{0}'.format(server.Variables.https_port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.logging_yaml.AddLines( ''' diff --git a/tests/gold_tests/h2/h2spec.test.py b/tests/gold_tests/h2/h2spec.test.py index fee2dd53300..ba841153980 100644 --- a/tests/gold_tests/h2/h2spec.test.py +++ b/tests/gold_tests/h2/h2spec.test.py @@ -38,7 +38,13 @@ ts.addDefaultSSLFiles() ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(httpbin.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { 'proxy.config.http.insert_request_via_str': 1, diff --git a/tests/gold_tests/h2/http2.test.py b/tests/gold_tests/h2/http2.test.py index 1635615ddaa..f6dfcf87973 100644 --- a/tests/gold_tests/h2/http2.test.py +++ b/tests/gold_tests/h2/http2.test.py @@ -139,7 +139,13 @@ ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { 'proxy.config.diags.debug.enabled': 1, diff --git a/tests/gold_tests/h2/http2_close_connection.test.py b/tests/gold_tests/h2/http2_close_connection.test.py index 7ad60d81609..5a16bd4cd0a 100644 --- a/tests/gold_tests/h2/http2_close_connection.test.py +++ b/tests/gold_tests/h2/http2_close_connection.test.py @@ -27,7 +27,13 @@ ts = Test.MakeATSProcess('ts', select_ports=True, enable_tls=True) ts.addDefaultSSLFiles() -ts.Disk.ssl_multicert_config.AddLine("dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key") +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { "proxy.config.http.server_ports": f"{ts.Variables.port} {ts.Variables.ssl_port}:ssl", diff --git a/tests/gold_tests/h2/http2_concurrent_streams.test.py b/tests/gold_tests/h2/http2_concurrent_streams.test.py index 7510b8e777b..79e6b9d088d 100644 --- a/tests/gold_tests/h2/http2_concurrent_streams.test.py +++ b/tests/gold_tests/h2/http2_concurrent_streams.test.py @@ -43,7 +43,13 @@ def __setupTS(self): 'proxy.config.http.insert_response_via_str': 2, }) self._ts.Disk.remap_config.AddLine(f"map / http://127.0.0.1:{self._server.Variables.http_port}") - self._ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self._ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) def run(self): tr = Test.AddTestRun() diff --git a/tests/gold_tests/h2/http2_empty_data_frame.test.py b/tests/gold_tests/h2/http2_empty_data_frame.test.py index d0e90389116..ae2caf7cadc 100644 --- a/tests/gold_tests/h2/http2_empty_data_frame.test.py +++ b/tests/gold_tests/h2/http2_empty_data_frame.test.py @@ -45,7 +45,13 @@ def __setupTS(self): 'proxy.config.http2.stream_error_rate_threshold': 0.1 # default }) self._ts.Disk.remap_config.AddLine(f"map / http://127.0.0.1:{self._server.Variables.Port}") - self._ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self._ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) def __setupClient(self): self._ts.Setup.CopyAs("clients/h2empty_data_frame.py", Test.RunDirectory) diff --git a/tests/gold_tests/h2/http2_flow_control.test.py b/tests/gold_tests/h2/http2_flow_control.test.py index 1d000c85509..c8d3dba242b 100644 --- a/tests/gold_tests/h2/http2_flow_control.test.py +++ b/tests/gold_tests/h2/http2_flow_control.test.py @@ -164,7 +164,13 @@ def _configure_trafficserver(self, tr: 'TestRun', is_outbound: bool, server_type configuration: self._max_concurrent_streams, }) - ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine(f'map / https://127.0.0.1:{self._server.Variables.https_port}') diff --git a/tests/gold_tests/h2/http2_priority.test.py b/tests/gold_tests/h2/http2_priority.test.py index 64b58c3fdb8..8b8168ca550 100644 --- a/tests/gold_tests/h2/http2_priority.test.py +++ b/tests/gold_tests/h2/http2_priority.test.py @@ -52,7 +52,13 @@ ts.addDefaultSSLFiles() ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { 'proxy.config.http2.stream_priority_enabled': 1, diff --git a/tests/gold_tests/h2/http2_rst_stream.test.py b/tests/gold_tests/h2/http2_rst_stream.test.py index caf2a711412..339e0dec60b 100644 --- a/tests/gold_tests/h2/http2_rst_stream.test.py +++ b/tests/gold_tests/h2/http2_rst_stream.test.py @@ -45,7 +45,13 @@ 'proxy.config.http.server_session_sharing.match': 'ip,sni,cert', }) ts.Disk.remap_config.AddLine(f'map / https://127.0.0.1:{server.Variables.https_port}') -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) tr = Test.AddTestRun('Client sends RST_STREAM after DATA frame') tr.Processes.Default.StartBefore(server) @@ -89,7 +95,13 @@ 'proxy.config.http.server_session_sharing.match': 'ip,sni,cert', }) ts.Disk.remap_config.AddLine(f'map / https://127.0.0.1:{server.Variables.https_port}') -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) tr = Test.AddTestRun('Client sends RST_STREAM after HEADERS frame') tr.Processes.Default.StartBefore(server) @@ -133,7 +145,13 @@ 'proxy.config.http.server_session_sharing.match': 'ip,sni,cert', }) ts.Disk.remap_config.AddLine(f'map / https://127.0.0.1:{server.Variables.https_port}') -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) tr = Test.AddTestRun('Server sends RST_STREAM after HEADERS frame') tr.Processes.Default.StartBefore(server) diff --git a/tests/gold_tests/h2/http2_write_threshold.test.py b/tests/gold_tests/h2/http2_write_threshold.test.py index 694037a7a56..53bfcae865e 100644 --- a/tests/gold_tests/h2/http2_write_threshold.test.py +++ b/tests/gold_tests/h2/http2_write_threshold.test.py @@ -89,7 +89,13 @@ def _configure_traffic_server( self._ts = tr.MakeATSProcess("ts", enable_tls=True, enable_cache=False) self._ts.addDefaultSSLFiles() - self._ts.Disk.ssl_multicert_config.AddLine("dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key") + self._ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self._ts.Disk.remap_config.AddLine(f"map / https://example.com:{server_port}/") diff --git a/tests/gold_tests/h2/httpbin.test.py b/tests/gold_tests/h2/httpbin.test.py index 342f175e435..3d04d603c2e 100644 --- a/tests/gold_tests/h2/httpbin.test.py +++ b/tests/gold_tests/h2/httpbin.test.py @@ -46,7 +46,13 @@ ts.addDefaultSSLFiles() ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(httpbin.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { 'proxy.config.http.insert_request_via_str': 1, diff --git a/tests/gold_tests/h2/nghttp.test.py b/tests/gold_tests/h2/nghttp.test.py index 071643a3498..b465e2766fc 100644 --- a/tests/gold_tests/h2/nghttp.test.py +++ b/tests/gold_tests/h2/nghttp.test.py @@ -52,7 +52,13 @@ httpbin.Variables.Port, Test.RunDirectory) ]) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { diff --git a/tests/gold_tests/h3/h3_sni_check.test.py b/tests/gold_tests/h3/h3_sni_check.test.py index 4ac57c66206..185ef70236d 100644 --- a/tests/gold_tests/h3/h3_sni_check.test.py +++ b/tests/gold_tests/h3/h3_sni_check.test.py @@ -67,7 +67,13 @@ def _configure_traffic_server(self, tr: 'TestRun'): self._ts = ts # Configure TLS for Traffic Server. self._ts.addDefaultSSLFiles() - self._ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self._ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self._ts.Disk.records_config.update( { 'proxy.config.diags.debug.enabled': 1, diff --git a/tests/gold_tests/headers/cachedIMSRange.test.py b/tests/gold_tests/headers/cachedIMSRange.test.py index 64af159c9f1..6bd064aef1c 100644 --- a/tests/gold_tests/headers/cachedIMSRange.test.py +++ b/tests/gold_tests/headers/cachedIMSRange.test.py @@ -109,7 +109,13 @@ ts = Test.MakeATSProcess("ts", enable_tls=True) ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache,x-cache-key,via') ts.addDefaultSSLFiles() -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { 'proxy.config.diags.debug.enabled': 1, diff --git a/tests/gold_tests/headers/forwarded.test.py b/tests/gold_tests/headers/forwarded.test.py index 8add15e404a..958e27a7c06 100644 --- a/tests/gold_tests/headers/forwarded.test.py +++ b/tests/gold_tests/headers/forwarded.test.py @@ -99,7 +99,13 @@ def baselineTsSetup(ts): 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir) }) - ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + ts.Disk.ssl_multicert_yaml.AddLines( + """ + ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key + """.split("\n")) ts.Disk.remap_config.AddLine('map http://www.no-oride.com http://127.0.0.1:{0}'.format(server.Variables.Port)) diff --git a/tests/gold_tests/headers/hsts.test.py b/tests/gold_tests/headers/hsts.test.py index e5438325165..9aaa866b509 100644 --- a/tests/gold_tests/headers/hsts.test.py +++ b/tests/gold_tests/headers/hsts.test.py @@ -47,7 +47,13 @@ ts.Disk.remap_config.AddLine('map https://www.example.com http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Test 1 - 200 Response tr = Test.AddTestRun() diff --git a/tests/gold_tests/headers/via.test.py b/tests/gold_tests/headers/via.test.py index 3ab495a2e6a..841736340ec 100644 --- a/tests/gold_tests/headers/via.test.py +++ b/tests/gold_tests/headers/via.test.py @@ -57,7 +57,13 @@ ts.Disk.remap_config.AddLine( 'map https://www.example.com http://127.0.0.1:{0}'.format(server.Variables.Port, ts.Variables.ssl_port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Set up to check the output after the tests have run. via_log_id = Test.Disk.File("via.log") diff --git a/tests/gold_tests/ip_allow/ip_allow.test.py b/tests/gold_tests/ip_allow/ip_allow.test.py index 0454a4e373f..0020e62d6b0 100644 --- a/tests/gold_tests/ip_allow/ip_allow.test.py +++ b/tests/gold_tests/ip_allow/ip_allow.test.py @@ -80,7 +80,13 @@ # Configure TLS for Traffic Server for HTTP/2. ts.addDefaultSSLFiles() -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { @@ -248,7 +254,13 @@ def _configure_traffic_server(self, tr: 'TestRun'): self._ts = ts # Configure TLS for Traffic Server. self._ts.addDefaultSSLFiles() - self._ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self._ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self._ts.Disk.records_config.update( { 'proxy.config.diags.debug.enabled': 1, diff --git a/tests/gold_tests/ip_allow/ip_category.test.py b/tests/gold_tests/ip_allow/ip_category.test.py index 76a8c1b7735..3e0f29bd1c7 100644 --- a/tests/gold_tests/ip_allow/ip_category.test.py +++ b/tests/gold_tests/ip_allow/ip_category.test.py @@ -218,7 +218,13 @@ def _configure_traffic_server(self) -> None: Test_ip_category._ts = ts ts.addDefaultSSLFiles() - ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { 'proxy.config.diags.debug.enabled': 1, diff --git a/tests/gold_tests/logging/new_log_flds.test.py b/tests/gold_tests/logging/new_log_flds.test.py index 94be8baec7d..b646e439449 100644 --- a/tests/gold_tests/logging/new_log_flds.test.py +++ b/tests/gold_tests/logging/new_log_flds.test.py @@ -53,7 +53,13 @@ ts.Disk.remap_config.AddLine( 'map https://reallyreallyreallyreallylong.com http://127.0.0.1:{1}/ip'.format(ts.Variables.ssl_port, httpbin.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.logging_yaml.AddLines( ''' diff --git a/tests/gold_tests/logging/qlog_quiche.test.py b/tests/gold_tests/logging/qlog_quiche.test.py index cb86cf17310..6d5a393407f 100644 --- a/tests/gold_tests/logging/qlog_quiche.test.py +++ b/tests/gold_tests/logging/qlog_quiche.test.py @@ -83,8 +83,13 @@ def _configure_traffic_server(self, tr: 'TestRun'): qlog: file_base: log/test_qlog # we expect to have log/test_qlog-.sqlog ''') - self._ts.Disk.ssl_multicert_config.AddLine( - f'dest_ip=* ssl_cert_name={ts.Variables.SSLDir}/server.pem ssl_key_name={ts.Variables.SSLDir}/server.key') + self._ts.Disk.ssl_multicert_yaml.AddLines( + f""" +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: {ts.Variables.SSLDir}/server.pem + ssl_key_name: {ts.Variables.SSLDir}/server.key +""".split("\n")) self._ts.Disk.remap_config.AddLine(f'map / http://127.0.0.1:{self._server.Variables.http_port}') diff --git a/tests/gold_tests/pluginTest/access_control/access_control.test.py b/tests/gold_tests/pluginTest/access_control/access_control.test.py index 8e1f7878170..65ed2b3035d 100644 --- a/tests/gold_tests/pluginTest/access_control/access_control.test.py +++ b/tests/gold_tests/pluginTest/access_control/access_control.test.py @@ -39,7 +39,13 @@ def setupOriginServer(self): def setupTS(self): self.ts = Test.MakeATSProcess("ts", enable_tls=True) self.ts.addDefaultSSLFiles() - self.ts.Disk.ssl_multicert_config.AddLine("dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key") + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts.Disk.records_config.update( { "proxy.config.diags.debug.enabled": 1, diff --git a/tests/gold_tests/pluginTest/cert_update/cert_update.test.py b/tests/gold_tests/pluginTest/cert_update/cert_update.test.py index 3d2766a4add..bbbaa31aa02 100644 --- a/tests/gold_tests/pluginTest/cert_update/cert_update.test.py +++ b/tests/gold_tests/pluginTest/cert_update/cert_update.test.py @@ -57,7 +57,13 @@ 'proxy.config.url_remap.pristine_host_hdr': 1 }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server1.pem ssl_key_name=server1.pem') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server1.pem + ssl_key_name: server1.pem +""".split("\n")) ts.Disk.remap_config.AddLines( [ diff --git a/tests/gold_tests/pluginTest/certifier/certifier.test.py b/tests/gold_tests/pluginTest/certifier/certifier.test.py index cb397fd1fd6..33e444f35ee 100644 --- a/tests/gold_tests/pluginTest/certifier/certifier.test.py +++ b/tests/gold_tests/pluginTest/certifier/certifier.test.py @@ -53,7 +53,13 @@ def setupTS(self): "proxy.config.ssl.server.cert.path": f'{self.ts.Variables.SSLDir}', "proxy.config.ssl.server.private_key.path": f'{self.ts.Variables.SSLDir}', }) - self.ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts.Disk.remap_config.AddLine(f"map / http://127.0.0.1:{self.server.Variables.http_port}/",) self.ts.Disk.plugin_config.AddLine( f'certifier.so -s {os.path.join(self.certPathDest, "store")} -m 1000 -c {os.path.join(self.certPathDest, "ca.cert")} -k {os.path.join(self.certPathDest, "ca.key")} -r {os.path.join(self.certPathDest, "ca-serial.txt")}' @@ -128,7 +134,13 @@ def setupTS(self): "proxy.config.ssl.server.cert.path": f'{self.ts.Variables.SSLDir}', "proxy.config.ssl.server.private_key.path": f'{self.ts.Variables.SSLDir}', }) - self.ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts.Disk.remap_config.AddLine(f"map / http://127.0.0.1:{self.server.Variables.http_port}/",) self.ts.Disk.plugin_config.AddLine( f'certifier.so -s {os.path.join(self.certPathDest, "store")} -m 1000 -c {os.path.join(self.certPathDest, "ca.cert")} -k {os.path.join(self.certPathDest, "ca.key")} -r {os.path.join(self.certPathDest, "ca-serial.txt")}' diff --git a/tests/gold_tests/pluginTest/client_context_dump/client_context_dump.test.py b/tests/gold_tests/pluginTest/client_context_dump/client_context_dump.test.py index 195caf5679b..7645684e339 100644 --- a/tests/gold_tests/pluginTest/client_context_dump/client_context_dump.test.py +++ b/tests/gold_tests/pluginTest/client_context_dump/client_context_dump.test.py @@ -40,7 +40,13 @@ 'proxy.config.ssl.client.private_key.path': '{}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=one.com.pem ssl_key_name=one.com.pem') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: one.com.pem + ssl_key_name: one.com.pem +""".split("\n")) ts.Disk.sni_yaml.AddLines( [ diff --git a/tests/gold_tests/pluginTest/healthchecks/healthchecks.test.py b/tests/gold_tests/pluginTest/healthchecks/healthchecks.test.py index bbf1a96f4cf..28479e079c2 100644 --- a/tests/gold_tests/pluginTest/healthchecks/healthchecks.test.py +++ b/tests/gold_tests/pluginTest/healthchecks/healthchecks.test.py @@ -72,7 +72,13 @@ def _configure_global_ts(self) -> None: "proxy.config.ssl.server.private_key.path": f'{ts.Variables.SSLDir}', "proxy.config.ssl.client.verify.server.policy": 'PERMISSIVE', }) - ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Other configuration. ts.Disk.records_config.update({ diff --git a/tests/gold_tests/pluginTest/ja3_fingerprint/ja3_fingerprint.test.py b/tests/gold_tests/pluginTest/ja3_fingerprint/ja3_fingerprint.test.py index e94c82196ab..665a170e7a6 100644 --- a/tests/gold_tests/pluginTest/ja3_fingerprint/ja3_fingerprint.test.py +++ b/tests/gold_tests/pluginTest/ja3_fingerprint/ja3_fingerprint.test.py @@ -96,7 +96,13 @@ def _configure_trafficserver(self) -> None: self._ts = Test.MakeATSProcess(name, enable_cache=False, enable_tls=True) JA3FingerprintTest._ts_counter += 1 self._ts.addDefaultSSLFiles() - self._ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self._ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) server_port = self._server.Variables.https_port self._ts.Disk.remap_config.AddLine(f'map https://https.server.com https://https.backend.com:{server_port}') diff --git a/tests/gold_tests/pluginTest/ja4_fingerprint/ja4_fingerprint.test.py b/tests/gold_tests/pluginTest/ja4_fingerprint/ja4_fingerprint.test.py index ea241579df0..23baa439c4b 100644 --- a/tests/gold_tests/pluginTest/ja4_fingerprint/ja4_fingerprint.test.py +++ b/tests/gold_tests/pluginTest/ja4_fingerprint/ja4_fingerprint.test.py @@ -125,7 +125,13 @@ def _configure_traffic_server(self, server_one: 'Process'): ts.Disk.remap_config.AddLine(f'map / http://localhost:{server_one.Variables.http_port}') - ts.Disk.ssl_multicert_config.AddLine(f'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.plugin_config.AddLine(f'ja4_fingerprint.so') diff --git a/tests/gold_tests/pluginTest/multiplexer/multiplexer.test.py b/tests/gold_tests/pluginTest/multiplexer/multiplexer.test.py index c4ffe1d4797..3468e6bc69c 100644 --- a/tests/gold_tests/pluginTest/multiplexer/multiplexer.test.py +++ b/tests/gold_tests/pluginTest/multiplexer/multiplexer.test.py @@ -130,7 +130,13 @@ def setupTS(self, skip_post): 'proxy.config.dns.nameservers': f'127.0.0.1:{self.dns.Variables.Port}', 'proxy.config.dns.resolv_conf': 'NULL', }) - self.ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) skip_remap_param = '' if skip_post: skip_remap_param = ' @pparam=proxy.config.multiplexer.skip_post_put=1' diff --git a/tests/gold_tests/pluginTest/server_push_preload/server_push_preload.test.py b/tests/gold_tests/pluginTest/server_push_preload/server_push_preload.test.py index af8dc4d940f..9ca134705db 100644 --- a/tests/gold_tests/pluginTest/server_push_preload/server_push_preload.test.py +++ b/tests/gold_tests/pluginTest/server_push_preload/server_push_preload.test.py @@ -71,7 +71,13 @@ ts.addDefaultSSLFiles() -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}/ @plugin=server_push_preload.so'.format(microserver.Variables.Port)) diff --git a/tests/gold_tests/pluginTest/sslheaders/sslheaders.test.py b/tests/gold_tests/pluginTest/sslheaders/sslheaders.test.py index 85c12b8c5d1..b5cdf9b2cc5 100644 --- a/tests/gold_tests/pluginTest/sslheaders/sslheaders.test.py +++ b/tests/gold_tests/pluginTest/sslheaders/sslheaders.test.py @@ -55,7 +55,13 @@ ts.Variables.port, ts.Variables.ssl_port)), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine('map http://bar.com http://127.0.0.1:{0}'.format(server.Variables.Port)) ts.Disk.remap_config.AddLine('map https://bar.com http://127.0.0.1:{0}'.format(server.Variables.Port)) diff --git a/tests/gold_tests/pluginTest/stek_share/stek_share.test.py b/tests/gold_tests/pluginTest/stek_share/stek_share.test.py index 8dcaf78ac4b..31f7241e07c 100644 --- a/tests/gold_tests/pluginTest/stek_share/stek_share.test.py +++ b/tests/gold_tests/pluginTest/stek_share/stek_share.test.py @@ -169,7 +169,13 @@ 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA' }) ts1.Disk.plugin_config.AddLine('stek_share.so {0}'.format(stek_share_conf_path_1)) -ts1.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=self_signed.crt ssl_key_name=self_signed.key') +ts1.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: self_signed.crt + ssl_key_name: self_signed.key +""".split("\n")) ts1.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) ts2.Disk.records_config.update( @@ -185,7 +191,13 @@ 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA' }) ts2.Disk.plugin_config.AddLine('stek_share.so {0}'.format(stek_share_conf_path_2)) -ts2.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=self_signed.crt ssl_key_name=self_signed.key') +ts2.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: self_signed.crt + ssl_key_name: self_signed.key +""".split("\n")) ts2.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) ts3.Disk.records_config.update( @@ -201,7 +213,13 @@ 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA' }) ts3.Disk.plugin_config.AddLine('stek_share.so {0}'.format(stek_share_conf_path_3)) -ts3.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=self_signed.crt ssl_key_name=self_signed.key') +ts3.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: self_signed.crt + ssl_key_name: self_signed.key +""".split("\n")) ts3.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) ts4.Disk.records_config.update( @@ -217,7 +235,13 @@ 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA' }) ts4.Disk.plugin_config.AddLine('stek_share.so {0}'.format(stek_share_conf_path_4)) -ts4.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=self_signed.crt ssl_key_name=self_signed.key') +ts4.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: self_signed.crt + ssl_key_name: self_signed.key +""".split("\n")) ts4.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) ts5.Disk.records_config.update( @@ -233,7 +257,13 @@ 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA' }) ts5.Disk.plugin_config.AddLine('stek_share.so {0}'.format(stek_share_conf_path_5)) -ts5.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=self_signed.crt ssl_key_name=self_signed.key') +ts5.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: self_signed.crt + ssl_key_name: self_signed.key +""".split("\n")) ts5.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) diff --git a/tests/gold_tests/pluginTest/test_hooks/test_hooks.test.py b/tests/gold_tests/pluginTest/test_hooks/test_hooks.test.py index 20ca7fbb1d3..b0cb46daf7d 100644 --- a/tests/gold_tests/pluginTest/test_hooks/test_hooks.test.py +++ b/tests/gold_tests/pluginTest/test_hooks/test_hooks.test.py @@ -49,7 +49,13 @@ 'proxy.config.diags.debug.tags': 'http|test_hooks', }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) Test.PrepareTestPlugin(os.path.join(Test.Variables.AtsTestPluginsDir, 'test_hooks.so'), ts) diff --git a/tests/gold_tests/pluginTest/traffic_dump/traffic_dump.test.py b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump.test.py index 645c5c52b8c..57e7146ed3f 100644 --- a/tests/gold_tests/pluginTest/traffic_dump/traffic_dump.test.py +++ b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump.test.py @@ -59,7 +59,13 @@ 'proxy.config.http.connect_ports': f"{server.Variables.http_port}", }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLines( [ diff --git a/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_http3.test.py b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_http3.test.py index 5c8bfa6255d..758b469979e 100644 --- a/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_http3.test.py +++ b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_http3.test.py @@ -60,7 +60,13 @@ 'proxy.config.ssl.client.verify.server.policy': 'PERMISSIVE', }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine(f'map https://www.client_only_tls.com/ http://127.0.0.1:{server.Variables.http_port}') ts.Disk.remap_config.AddLine(f'map https://www.tls.com/ https://127.0.0.1:{server.Variables.https_port}') diff --git a/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_response_body.test.py b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_response_body.test.py index f816b63948e..1b296b5e6a0 100644 --- a/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_response_body.test.py +++ b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_response_body.test.py @@ -52,7 +52,13 @@ 'proxy.config.ssl.client.verify.server.policy': 'PERMISSIVE', }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLines([ f'map / http://127.0.0.1:{server.Variables.http_port}', diff --git a/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_sni_filter.test.py b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_sni_filter.test.py index 710d2c9742d..b3ff3ca00e0 100644 --- a/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_sni_filter.test.py +++ b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump_sni_filter.test.py @@ -53,7 +53,13 @@ 'proxy.config.ssl.client.verify.server.policy': 'PERMISSIVE', }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine(f'map / https://127.0.0.1:{server.Variables.https_port}') diff --git a/tests/gold_tests/pluginTest/transform/transaction_data_sink.test.py b/tests/gold_tests/pluginTest/transform/transaction_data_sink.test.py index 46d71b84d90..a632521da61 100644 --- a/tests/gold_tests/pluginTest/transform/transaction_data_sink.test.py +++ b/tests/gold_tests/pluginTest/transform/transaction_data_sink.test.py @@ -51,7 +51,13 @@ def _setupTS(self): }) self.ts.addDefaultSSLFiles() self.ts.Disk.remap_config.AddLine(f'map / http://localhost:{self.server.Variables.http_port}/') - self.ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts.Disk.plugin_config.AddLine('txn_data_sink.so') # All of the bodies that contained "not_dumped" were not configured to diff --git a/tests/gold_tests/pluginTest/tsapi/test_TSHttpSsnInfo.test.py b/tests/gold_tests/pluginTest/tsapi/test_TSHttpSsnInfo.test.py index 3d1dad1a2f3..2685ee3ef78 100644 --- a/tests/gold_tests/pluginTest/tsapi/test_TSHttpSsnInfo.test.py +++ b/tests/gold_tests/pluginTest/tsapi/test_TSHttpSsnInfo.test.py @@ -49,7 +49,13 @@ ts.Disk.remap_config.AddLines(['map /httpbin/ http://127.0.0.1:{0}/'.format(httpbin.Variables.Port)]) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) Test.PrepareTestPlugin( os.path.join(Test.Variables.AtsBuildGoldTestsDir, 'pluginTest', 'tsapi', '.libs', 'test_TSHttpSsnInfo.so'), ts) diff --git a/tests/gold_tests/pluginTest/tsapi/test_TSVConnPPInfo.test.py b/tests/gold_tests/pluginTest/tsapi/test_TSVConnPPInfo.test.py index 0c45109d971..3adea661f33 100644 --- a/tests/gold_tests/pluginTest/tsapi/test_TSVConnPPInfo.test.py +++ b/tests/gold_tests/pluginTest/tsapi/test_TSVConnPPInfo.test.py @@ -49,7 +49,13 @@ ts.Disk.remap_config.AddLines(['map /httpbin/ http://127.0.0.1:{0}/'.format(httpbin.Variables.Port)]) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) Test.PrepareTestPlugin( os.path.join(Test.Variables.AtsBuildGoldTestsDir, 'pluginTest', 'tsapi', '.libs', 'test_TSVConnPPInfo.so'), ts) diff --git a/tests/gold_tests/pluginTest/tsapi/tsapi.test.py b/tests/gold_tests/pluginTest/tsapi/tsapi.test.py index 84b5ba4be6e..2b4e2e278f5 100644 --- a/tests/gold_tests/pluginTest/tsapi/tsapi.test.py +++ b/tests/gold_tests/pluginTest/tsapi/tsapi.test.py @@ -55,7 +55,13 @@ 'proxy.config.diags.debug.tags': f'http|{plugin_name}', }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) rp = os.path.join(Test.Variables.AtsBuildGoldTestsDir, 'pluginTest', 'tsapi', '.libs', f'{plugin_name}.so') ts.Setup.Copy(rp, ts.Env['PROXY_CONFIG_PLUGIN_PLUGIN_DIR']) diff --git a/tests/gold_tests/pluginTest/txn_box/basic/txn_box_tls-cert.test.py b/tests/gold_tests/pluginTest/txn_box/basic/txn_box_tls-cert.test.py index 00181e4da68..496e5f08954 100644 --- a/tests/gold_tests/pluginTest/txn_box/basic/txn_box_tls-cert.test.py +++ b/tests/gold_tests/pluginTest/txn_box/basic/txn_box_tls-cert.test.py @@ -58,4 +58,10 @@ 'proxy.config.ssl.client.cert.path': ts.Variables.SSLDir, 'proxy.config.ssl.client.cert.filename': "bravo-signed.cert" }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) diff --git a/tests/gold_tests/pluginTest/txn_box/basic/txn_box_tls.test.py b/tests/gold_tests/pluginTest/txn_box/basic/txn_box_tls.test.py index 080753460e8..e23165d4ce5 100644 --- a/tests/gold_tests/pluginTest/txn_box/basic/txn_box_tls.test.py +++ b/tests/gold_tests/pluginTest/txn_box/basic/txn_box_tls.test.py @@ -53,4 +53,10 @@ 'proxy.config.http.server_ports': '{0} {1}:ssl'.format(ts.Variables.port, ts.Variables.ssl_port), 'proxy.config.ssl.client.verify.server.policy': 'DISABLED' }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) diff --git a/tests/gold_tests/pluginTest/txn_box/ct_header/txn_box_ct_header.test.py b/tests/gold_tests/pluginTest/txn_box/ct_header/txn_box_ct_header.test.py index c5fc5e9762e..07cae3ca260 100644 --- a/tests/gold_tests/pluginTest/txn_box/ct_header/txn_box_ct_header.test.py +++ b/tests/gold_tests/pluginTest/txn_box/ct_header/txn_box_ct_header.test.py @@ -56,4 +56,10 @@ 'proxy.config.http.server_ports': '{0} {1}:ssl'.format(ts.Variables.port, ts.Variables.ssl_port), 'proxy.config.ssl.client.verify.server.policy': 'DISABLED' }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) diff --git a/tests/gold_tests/pluginTest/txn_box/prod/txn_box_mTLS.test.py b/tests/gold_tests/pluginTest/txn_box/prod/txn_box_mTLS.test.py index c76d0fab7e1..bfb76b22c5a 100644 --- a/tests/gold_tests/pluginTest/txn_box/prod/txn_box_mTLS.test.py +++ b/tests/gold_tests/pluginTest/txn_box/prod/txn_box_mTLS.test.py @@ -67,4 +67,10 @@ 'proxy.config.ssl.client.certification_level': 2, 'proxy.config.http.server_ports': '{0} {1}:ssl'.format(ts.Variables.port, ts.Variables.ssl_port) }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) diff --git a/tests/gold_tests/pluginTest/txn_box/ramp/multi_ramp_common.py b/tests/gold_tests/pluginTest/txn_box/ramp/multi_ramp_common.py index b7322dc8e88..9feddac59de 100644 --- a/tests/gold_tests/pluginTest/txn_box/ramp/multi_ramp_common.py +++ b/tests/gold_tests/pluginTest/txn_box/ramp/multi_ramp_common.py @@ -97,7 +97,13 @@ def ramp_test_fixup(tr): 'proxy.config.ssl.server.cipher_suite': 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2' }) - ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + ts.Disk.ssl_multicert_yaml.AddLines( + """ + ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key + """.split("\n")) pv_client = tr.Variables.CLIENT diff --git a/tests/gold_tests/pluginTest/txn_box/remap/txn_box_remap-base.test.py b/tests/gold_tests/pluginTest/txn_box/remap/txn_box_remap-base.test.py index 04b08f7dcb4..6e16c73cdec 100644 --- a/tests/gold_tests/pluginTest/txn_box/remap/txn_box_remap-base.test.py +++ b/tests/gold_tests/pluginTest/txn_box/remap/txn_box_remap-base.test.py @@ -60,4 +60,10 @@ 'proxy.config.ssl.client.verify.server.policy': "disabled" }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) diff --git a/tests/gold_tests/pluginTest/url_sig/url_sig.test.py b/tests/gold_tests/pluginTest/url_sig/url_sig.test.py index 373255cd633..16c2927ba07 100644 --- a/tests/gold_tests/pluginTest/url_sig/url_sig.test.py +++ b/tests/gold_tests/pluginTest/url_sig/url_sig.test.py @@ -96,7 +96,13 @@ 'proxy.config.ssl.server.private_key.path': ts.Variables.SSLDir, }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Use unchanged incoming URL. # diff --git a/tests/gold_tests/post/post-continue.test.py b/tests/gold_tests/post/post-continue.test.py index 5dfd75044c1..b170f0e374e 100644 --- a/tests/gold_tests/post/post-continue.test.py +++ b/tests/gold_tests/post/post-continue.test.py @@ -47,7 +47,13 @@ ts2.addDefaultSSLFiles() ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.http_port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir), @@ -56,7 +62,13 @@ 'proxy.config.diags.debug.tags': 'http', }) ts2.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.http_port)) -ts2.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts2.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts2.Disk.records_config.update( { 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir), diff --git a/tests/gold_tests/post/post-early-return.test.py b/tests/gold_tests/post/post-early-return.test.py index 82879eb4015..923e23f4f97 100644 --- a/tests/gold_tests/post/post-early-return.test.py +++ b/tests/gold_tests/post/post-early-return.test.py @@ -51,7 +51,13 @@ 'map /five http://127.0.0.1:{0}'.format(Test.Variables.upstream_port5), 'map /six http://127.0.0.1:{0}'.format(Test.Variables.upstream_port6), ]) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir), diff --git a/tests/gold_tests/post_slow_server/post_slow_server.test.py b/tests/gold_tests/post_slow_server/post_slow_server.test.py index 4447eb938bc..1f4612b43dd 100644 --- a/tests/gold_tests/post_slow_server/post_slow_server.test.py +++ b/tests/gold_tests/post_slow_server/post_slow_server.test.py @@ -41,7 +41,13 @@ 'proxy.config.http2.no_activity_timeout_in': 150, }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) Test.GetTcpPort("server_port") diff --git a/tests/gold_tests/proxy_protocol/proxy_protocol.test.py b/tests/gold_tests/proxy_protocol/proxy_protocol.test.py index bd008b9a6f0..51508499eef 100644 --- a/tests/gold_tests/proxy_protocol/proxy_protocol.test.py +++ b/tests/gold_tests/proxy_protocol/proxy_protocol.test.py @@ -44,7 +44,13 @@ def setupTS(self, name, enable_cp): enable_proxy_protocol_cp_src=enable_cp) self.ts.addDefaultSSLFiles() - self.ts.Disk.ssl_multicert_config.AddLine("dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key") + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts.Disk.remap_config.AddLine(f"map / http://127.0.0.1:{self.server.Variables.http_port}/") @@ -146,7 +152,13 @@ def setupTS(self, tr: 'TestRun') -> None: self._ts = tr.MakeATSProcess(process_name, enable_tls=True, enable_cache=False) self._ts.addDefaultSSLFiles() - self._ts.Disk.ssl_multicert_config.AddLine("dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key") + self._ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) scheme = 'https' if self._is_tls_to_origin else 'http' server_port = self._server.Variables.https_port if self._is_tls_to_origin else self._server.Variables.http_port self._ts.Disk.remap_config.AddLine(f"map / {scheme}://backend.pp.origin.com:{server_port}/") diff --git a/tests/gold_tests/remap/remap_https.test.py b/tests/gold_tests/remap/remap_https.test.py index 19f74ae8309..0c53fa2f4c9 100644 --- a/tests/gold_tests/remap/remap_https.test.py +++ b/tests/gold_tests/remap/remap_https.test.py @@ -57,7 +57,13 @@ ts.Disk.remap_config.AddLine( 'map https://www.anotherexample.com https://127.0.0.1:{0}'.format(server2.Variables.SSL_Port, ts.Variables.ssl_port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # call localhost straight tr = Test.AddTestRun() diff --git a/tests/gold_tests/remap/remap_ws.test.py b/tests/gold_tests/remap/remap_ws.test.py index 5d677a0f9cc..3e122446415 100644 --- a/tests/gold_tests/remap/remap_ws.test.py +++ b/tests/gold_tests/remap/remap_ws.test.py @@ -51,7 +51,13 @@ 'map wss://www.example.com:{1} ws://127.0.0.1:{0}'.format(server.Variables.Port, ts.Variables.ssl_port), ]) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) if not Condition.CurlUsingUnixDomainSocket(): # wss mapping diff --git a/tests/gold_tests/slow_post/server_abort.test.py b/tests/gold_tests/slow_post/server_abort.test.py index 1004bcdb6a3..98362c1463a 100644 --- a/tests/gold_tests/slow_post/server_abort.test.py +++ b/tests/gold_tests/slow_post/server_abort.test.py @@ -30,7 +30,13 @@ # on the origin server so that it aborts the connection upon receiving a # request 'map / https://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=aaa-signed.pem ssl_key_name=aaa-signed.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: aaa-signed.pem + ssl_key_name: aaa-signed.key +""".split("\n")) ts.Disk.records_config.update( { 'proxy.config.diags.debug.tags': 'http|dns', diff --git a/tests/gold_tests/timeout/accept_timeout.test.py b/tests/gold_tests/timeout/accept_timeout.test.py index 1521a129a58..80a7d44dcce 100644 --- a/tests/gold_tests/timeout/accept_timeout.test.py +++ b/tests/gold_tests/timeout/accept_timeout.test.py @@ -38,7 +38,13 @@ 'proxy.config.net.defer_accept': 0 # Must turn off defer accept to test the raw TCP case }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # case 1 TLS with no data tr = Test.AddTestRun("tr") diff --git a/tests/gold_tests/timeout/active_timeout.test.py b/tests/gold_tests/timeout/active_timeout.test.py index 5f5d1d52ec9..5227cc0e93c 100644 --- a/tests/gold_tests/timeout/active_timeout.test.py +++ b/tests/gold_tests/timeout/active_timeout.test.py @@ -43,7 +43,13 @@ ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}/'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) tr = Test.AddTestRun("tr") tr.Processes.Default.StartBefore(server) diff --git a/tests/gold_tests/timeout/http2_no_activity_timeout.test.py b/tests/gold_tests/timeout/http2_no_activity_timeout.test.py index bab22021048..ab910e0732c 100644 --- a/tests/gold_tests/timeout/http2_no_activity_timeout.test.py +++ b/tests/gold_tests/timeout/http2_no_activity_timeout.test.py @@ -75,9 +75,13 @@ def _configure_traffic_server(self, tr: 'TestRun'): self._ts.addSSLfile("ssl/cert.crt") self._ts.addSSLfile("ssl/private-key.key") - self._ts.Disk.ssl_multicert_config.AddLine( - f'dest_ip=* ssl_cert_name={self._ts.Variables.SSLDir}/cert.crt ' - f'ssl_key_name={self._ts.Variables.SSLDir}/private-key.key') + self._ts.Disk.ssl_multicert_yaml.AddLines( + f""" +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: {self._ts.Variables.SSLDir}/cert.crt + ssl_key_name: {self._ts.Variables.SSLDir}/private-key.key +""".split("\n")) self._ts.Disk.records_config.update( { diff --git a/tests/gold_tests/timeout/inactive_client_timeout.test.py b/tests/gold_tests/timeout/inactive_client_timeout.test.py index 6c0a06f3f2c..84d3de4adf6 100644 --- a/tests/gold_tests/timeout/inactive_client_timeout.test.py +++ b/tests/gold_tests/timeout/inactive_client_timeout.test.py @@ -46,7 +46,13 @@ 'map / http://127.0.0.1:{0}'.format(server.Variables.http_port), ]) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # # Test 1: Verify that server delay does not trigger client activity timeout. diff --git a/tests/gold_tests/timeout/inactive_timeout.test.py b/tests/gold_tests/timeout/inactive_timeout.test.py index c1fc3d8ed0b..2265763eff7 100644 --- a/tests/gold_tests/timeout/inactive_timeout.test.py +++ b/tests/gold_tests/timeout/inactive_timeout.test.py @@ -40,7 +40,13 @@ ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}/'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) tr = Test.AddTestRun("tr") tr.Processes.Default.StartBefore(server) diff --git a/tests/gold_tests/timeout/quic_no_activity_timeout.test.py b/tests/gold_tests/timeout/quic_no_activity_timeout.test.py index 0b688c8b0a5..f50146f5bea 100644 --- a/tests/gold_tests/timeout/quic_no_activity_timeout.test.py +++ b/tests/gold_tests/timeout/quic_no_activity_timeout.test.py @@ -74,9 +74,13 @@ def _configure_traffic_server(self, tr: 'TestRun'): self._ts.Disk.records_config.update(self.extra_recs) self._ts.Disk.remap_config.AddLine(f'map / http://127.0.0.1:{self._server.Variables.http_port}') - self._ts.Disk.ssl_multicert_config.AddLine( - f'dest_ip=* ssl_cert_name={self._ts.Variables.SSLDir}/cert.crt ssl_key_name={self._ts.Variables.SSLDir}/private-key.key' - ) + self._ts.Disk.ssl_multicert_yaml.AddLines( + f""" +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: {self._ts.Variables.SSLDir}/cert.crt + ssl_key_name: {self._ts.Variables.SSLDir}/private-key.key +""".split("\n")) def run(self, check_for_max_idle_timeout=False): """Run the test.""" diff --git a/tests/gold_tests/tls/allow-plain.test.py b/tests/gold_tests/tls/allow-plain.test.py index d4791383f4f..0e2802b868d 100644 --- a/tests/gold_tests/tls/allow-plain.test.py +++ b/tests/gold_tests/tls/allow-plain.test.py @@ -53,7 +53,13 @@ 'map /post http://127.0.0.1:{0}/post'.format(server.Variables.http_port), ]) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) big_post_body = "0123456789" * 50000 big_post_body_file = open(os.path.join(Test.RunDirectory, "big_post_body"), "w") diff --git a/tests/gold_tests/tls/exit_on_cert_load_fail.test.py b/tests/gold_tests/tls/exit_on_cert_load_fail.test.py index c075e1a357c..cbac56e6672 100644 --- a/tests/gold_tests/tls/exit_on_cert_load_fail.test.py +++ b/tests/gold_tests/tls/exit_on_cert_load_fail.test.py @@ -58,7 +58,13 @@ def _configure_traffic_server(self, tr: 'TestRun'): # Also setup the server certs so that issues are limited to client # cert loading. self._ts.addDefaultSSLFiles() - self._ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self._ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self._ts.Disk.records_config.update( { 'proxy.config.ssl.server.cert.path': f'{ts.Variables.SSLDir}', diff --git a/tests/gold_tests/tls/ssl_key_dialog.test.py b/tests/gold_tests/tls/ssl_key_dialog.test.py index dd9438f371c..107e4d722fe 100644 --- a/tests/gold_tests/tls/ssl_key_dialog.test.py +++ b/tests/gold_tests/tls/ssl_key_dialog.test.py @@ -39,10 +39,14 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLines( - [ - 'dest_ip=* ssl_cert_name=passphrase.pem ssl_key_name=passphrase.key ssl_key_dialog="exec:/bin/bash -c \'echo -n passphrase\'"', - ]) +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: passphrase.pem + ssl_key_name: passphrase.key + ssl_key_dialog: "exec:/bin/bash -c 'echo -n passphrase'" +""".split("\n")) request_header = {"headers": "GET / HTTP/1.1\r\nHost: bogus\r\n\r\n", "timestamp": "1469733493.993", "body": ""} response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "timestamp": "1469733493.993", "body": "success!"} @@ -63,12 +67,16 @@ tr2 = Test.AddTestRun("Update config files") # Update the multicert config -sslcertpath = ts.Disk.ssl_multicert_config.AbsPath +sslcertpath = ts.Disk.ssl_multicert_yaml.AbsPath tr2.Disk.File(sslcertpath, id="ssl_multicert_config", typename="ats:config"), tr2.Disk.ssl_multicert_config.AddLines( - [ - 'dest_ip=* ssl_cert_name=passphrase2.pem ssl_key_name=passphrase2.key ssl_key_dialog="exec:/bin/bash -c \'echo -n passphrase\'"', - ]) + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: passphrase2.pem + ssl_key_name: passphrase2.key + ssl_key_dialog: "exec:/bin/bash -c 'echo -n passphrase'" +""".split("\n")) tr2.StillRunningAfter = ts tr2.StillRunningAfter = server tr2.Processes.Default.Command = 'echo Updated configs' @@ -90,7 +98,7 @@ p.Env = ts.Env p.ReturnCode = 0 await_config_reload = tr.Processes.Process(f'config_reload_succeeded', 'sleep 30') -await_config_reload.Ready = When.FileContains(ts.Disk.diags_log.Name, "ssl_multicert.config finished loading", 2) +await_config_reload.Ready = When.FileContains(ts.Disk.diags_log.Name, "ssl_multicert.yaml finished loading", 2) p.StartBefore(await_config_reload) tr3 = Test.AddTestRun("use a key with passphrase") diff --git a/tests/gold_tests/tls/ssl_multicert_loader.test.py b/tests/gold_tests/tls/ssl_multicert_loader.test.py index 60834b1dbc6..6b74da7c532 100644 --- a/tests/gold_tests/tls/ssl_multicert_loader.test.py +++ b/tests/gold_tests/tls/ssl_multicert_loader.test.py @@ -15,7 +15,7 @@ # limitations under the License. Test.Summary = ''' -Test reloading ssl_multicert.config with errors and keeping around the old ssl config structure +Test reloading ssl_multicert.yaml with errors and keeping around the old ssl config structure ''' sni_domain = 'example.com' @@ -39,7 +39,13 @@ ts.Disk.remap_config.AddLine(f'map / http://127.0.0.1:{server.Variables.Port}') -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) tr = Test.AddTestRun("ensure we can connect for SNI $sni_domain") tr.Processes.Default.StartBefore(Test.Processes.ts) @@ -53,15 +59,19 @@ tr.Processes.Default.Streams.stderr = Testers.IncludesExpression(f"CN={sni_domain}", "Check response") tr2 = Test.AddTestRun("Update config files") -# Update the configs -sslcertpath = ts.Disk.ssl_multicert_config.AbsPath - -tr2.Disk.File(sslcertpath, id="ssl_multicert_config", typename="ats:config") -tr2.Disk.ssl_multicert_config.AddLines( - [ - 'ssl_cert_name=server_does_not_exist.pem ssl_key_name=server_does_not_exist.key', - 'dest_ip=* ssl_cert_name=server.pem_doesnotexist ssl_key_name=server.key', - ]) +# Update the configs - overwrite the ssl_multicert.yaml file with an invalid config +sslcertpath = ts.Disk.ssl_multicert_yaml.AbsPath + +tr2.Disk.File(sslcertpath, id="ssl_multicert_update", typename="ats:config") +tr2.Disk.ssl_multicert_update.AddLines( + """ +ssl_multicert: + - ssl_cert_name: server_does_not_exist.pem + ssl_key_name: server_does_not_exist.key + - dest_ip: "*" + ssl_cert_name: server.pem_doesnotexist + ssl_key_name: server.key +""".split("\n")) tr2.StillRunningAfter = ts tr2.StillRunningAfter = server tr2.Processes.Default.Command = 'echo Updated configs' @@ -76,7 +86,7 @@ tr2reload.Processes.Default.ReturnCode = 0 ts.Disk.diags_log.Content = Testers.ContainsExpression('ERROR: ', 'ERROR') -# Reload of ssl_multicert.config should fail, BUT the old config structure +# Reload of ssl_multicert.yaml should fail, BUT the old config structure # should be in place to successfully answer for the test domain tr3 = Test.AddTestRun("Make request again for $sni_domain") # Wait for the reload to complete @@ -95,9 +105,13 @@ # to catch if the current default (1) changes in the future ts2 = Test.MakeATSProcess("ts2", enable_tls=True) -ts2.Disk.ssl_multicert_config.AddLines([ - 'dest_ip=* ssl_cert_name=server.pem_doesnotexist ssl_key_name=server.key', -]) +ts2.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem_doesnotexist + ssl_key_name: server.key +""".split("\n")) tr4 = Test.AddTestRun() tr4.Processes.Default.Command = 'echo Waiting' diff --git a/tests/gold_tests/tls/tls.test.py b/tests/gold_tests/tls/tls.test.py index 60789376ca0..5ac2951446d 100644 --- a/tests/gold_tests/tls/tls.test.py +++ b/tests/gold_tests/tls/tls.test.py @@ -65,7 +65,13 @@ ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir), diff --git a/tests/gold_tests/tls/tls_0rtt_server.test.py b/tests/gold_tests/tls/tls_0rtt_server.test.py index 76047758fa8..49e6d5f6cd3 100644 --- a/tests/gold_tests/tls/tls_0rtt_server.test.py +++ b/tests/gold_tests/tls/tls_0rtt_server.test.py @@ -111,7 +111,13 @@ 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA' }) -ts1.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts1.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts1.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) @@ -136,7 +142,13 @@ 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA' }) -ts2.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts2.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts2.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) diff --git a/tests/gold_tests/tls/tls_bad_alpn.test.py b/tests/gold_tests/tls/tls_bad_alpn.test.py index 027eed148df..513aba7e22f 100644 --- a/tests/gold_tests/tls/tls_bad_alpn.test.py +++ b/tests/gold_tests/tls/tls_bad_alpn.test.py @@ -34,7 +34,13 @@ ts.addSSLfile("ssl/server.key") # Make sure the TS server certs are different from the origin certs -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_check_cert_select_plugin.test.py b/tests/gold_tests/tls/tls_check_cert_select_plugin.test.py index b4b4d8f5870..6cc069ea03e 100644 --- a/tests/gold_tests/tls/tls_check_cert_select_plugin.test.py +++ b/tests/gold_tests/tls/tls_check_cert_select_plugin.test.py @@ -44,12 +44,18 @@ ts.Disk.remap_config.AddLine('map / https://foo.com:{1}'.format(ts.Variables.ssl_port, server.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLines( - [ - 'dest_ip=127.0.0.1 ssl_cert_name=signed-foo.pem ssl_key_name=signed-foo.key', - 'ssl_cert_name=signed2-bar.pem ssl_key_name=signed-bar.key', - 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key', - ]) +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: 127.0.0.1 + ssl_cert_name: signed-foo.pem + ssl_key_name: signed-foo.key + - ssl_cert_name: signed2-bar.pem + ssl_key_name: signed-bar.key + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) Test.PrepareTestPlugin(os.path.join(Test.Variables.AtsTestPluginsDir, 'ssl_secret_load_test.so'), ts) diff --git a/tests/gold_tests/tls/tls_check_cert_selection.test.py b/tests/gold_tests/tls/tls_check_cert_selection.test.py index d5c18867f07..bc3006193a6 100644 --- a/tests/gold_tests/tls/tls_check_cert_selection.test.py +++ b/tests/gold_tests/tls/tls_check_cert_selection.test.py @@ -41,12 +41,17 @@ ts.Disk.remap_config.AddLine('map / https://foo.com:{1}'.format(ts.Variables.ssl_port, server.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLines( - [ - 'dest_ip=127.0.0.1 ssl_cert_name=signed-foo.pem ssl_key_name=signed-foo.key', - 'ssl_cert_name=signed2-bar.pem ssl_key_name=signed-bar.key', - 'dest_ip=* ssl_cert_name=combo.pem', - ]) +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "127.0.0.1" + ssl_cert_name: signed-foo.pem + ssl_key_name: signed-foo.key + - ssl_cert_name: signed2-bar.pem + ssl_key_name: signed-bar.key + - dest_ip: "*" + ssl_cert_name: combo.pem +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_check_cert_selection_reload.test.py b/tests/gold_tests/tls/tls_check_cert_selection_reload.test.py index 51d092a844e..84d526bf4fd 100644 --- a/tests/gold_tests/tls/tls_check_cert_selection_reload.test.py +++ b/tests/gold_tests/tls/tls_check_cert_selection_reload.test.py @@ -39,11 +39,14 @@ ts.Disk.remap_config.AddLine('map /stuff https://foo.com:{1}'.format(ts.Variables.ssl_port, server.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLines( - [ - 'ssl_cert_name=signed-bar.pem ssl_key_name=signed-bar.key', - 'dest_ip=* ssl_cert_name=combo.pem', - ]) +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - ssl_cert_name: signed-bar.pem + ssl_key_name: signed-bar.key + - dest_ip: "*" + ssl_cert_name: combo.pem +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all @@ -106,8 +109,7 @@ tr = Test.AddTestRun("Try with signer 1 again") # Wait for the reload to complete -tr.Processes.Default.StartBefore( - server3, ready=When.FileContains(ts.Disk.diags_log.Name, 'ssl_multicert.config finished loading', 2)) +tr.Processes.Default.StartBefore(server3, ready=When.FileContains(ts.Disk.diags_log.Name, 'ssl_multicert.yaml finished loading', 2)) tr.StillRunningAfter = ts tr.StillRunningAfter = server tr.MakeCurlCommand( diff --git a/tests/gold_tests/tls/tls_check_dual_cert_selection.test.py b/tests/gold_tests/tls/tls_check_dual_cert_selection.test.py index cff5c542803..5fd3c2ad71c 100644 --- a/tests/gold_tests/tls/tls_check_dual_cert_selection.test.py +++ b/tests/gold_tests/tls/tls_check_dual_cert_selection.test.py @@ -48,12 +48,17 @@ ts.Disk.remap_config.AddLine('map / https://foo.com:{1}'.format(ts.Variables.ssl_port, server.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLines( - [ - 'ssl_cert_name=signed-foo-ec.pem,signed-foo.pem ssl_key_name=signed-foo-ec.key,signed-foo.key', - 'ssl_cert_name=signed-san-ec.pem,signed-san.pem ssl_key_name=signed-san-ec.key,signed-san.key', - 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key', - ]) +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - ssl_cert_name: signed-foo-ec.pem,signed-foo.pem + ssl_key_name: signed-foo-ec.key,signed-foo.key + - ssl_cert_name: signed-san-ec.pem,signed-san.pem + ssl_key_name: signed-san-ec.key,signed-san.key + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_check_dual_cert_selection2.test.py b/tests/gold_tests/tls/tls_check_dual_cert_selection2.test.py index 94b01e8ded3..b443564c0c2 100644 --- a/tests/gold_tests/tls/tls_check_dual_cert_selection2.test.py +++ b/tests/gold_tests/tls/tls_check_dual_cert_selection2.test.py @@ -49,12 +49,14 @@ ts.Disk.remap_config.AddLine('map / https://foo.com:{1}'.format(ts.Variables.ssl_port, server.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLines( - [ - 'ssl_cert_name=combined-ec.pem,combined.pem', - 'ssl_cert_name=signed-foo-ec.pem,signed-foo.pem', - 'dest_ip=* ssl_cert_name=signed-san-ec.pem,signed-san.pem', - ]) +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - ssl_cert_name: combined-ec.pem,combined.pem + - ssl_cert_name: signed-foo-ec.pem,signed-foo.pem + - dest_ip: "*" + ssl_cert_name: signed-san-ec.pem,signed-san.pem +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_check_dual_cert_selection_plugin.test.py b/tests/gold_tests/tls/tls_check_dual_cert_selection_plugin.test.py index 14b3b2fe1cc..fbc1dea836e 100644 --- a/tests/gold_tests/tls/tls_check_dual_cert_selection_plugin.test.py +++ b/tests/gold_tests/tls/tls_check_dual_cert_selection_plugin.test.py @@ -50,12 +50,17 @@ ts.Disk.remap_config.AddLine('map / https://foo.com:{1}'.format(ts.Variables.ssl_port, server.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLines( - [ - 'ssl_cert_name=signed-foo-ec.pem,signed-foo.pem ssl_key_name=signed-foo-ec.key,signed-foo.key', - 'ssl_cert_name=signed-san-ec.pem,signed-san.pem ssl_key_name=signed-san-ec.key,signed-san.key', - 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key', - ]) +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - ssl_cert_name: signed-foo-ec.pem,signed-foo.pem + ssl_key_name: signed-foo-ec.key,signed-foo.key + - ssl_cert_name: signed-san-ec.pem,signed-san.pem + ssl_key_name: signed-san-ec.key,signed-san.key + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) Test.PrepareTestPlugin(os.path.join(Test.Variables.AtsTestPluginsDir, 'ssl_secret_load_test.so'), ts) diff --git a/tests/gold_tests/tls/tls_client_alpn_configuration.test.py b/tests/gold_tests/tls/tls_client_alpn_configuration.test.py index dc57b3ae38d..1bd5cffcd26 100644 --- a/tests/gold_tests/tls/tls_client_alpn_configuration.test.py +++ b/tests/gold_tests/tls/tls_client_alpn_configuration.test.py @@ -107,7 +107,13 @@ def _configure_trafficserver( 'proxy.config.ssl.client.alpn_protocols': records_config_alpn, }) - ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) conf_remap_specification = '' if conf_remap_alpn is not None: diff --git a/tests/gold_tests/tls/tls_client_cert.test.py b/tests/gold_tests/tls/tls_client_cert.test.py index c848c735faa..605ad843c12 100644 --- a/tests/gold_tests/tls/tls_client_cert.test.py +++ b/tests/gold_tests/tls/tls_client_cert.test.py @@ -91,7 +91,13 @@ 'proxy.config.ssl.client.verify.server.policy': 'PERMISSIVE', }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine('map /case1 https://127.0.0.1:{0}/'.format(server.Variables.SSL_Port)) ts.Disk.remap_config.AddLine('map /case2 https://127.0.0.1:{0}/'.format(server2.Variables.SSL_Port)) diff --git a/tests/gold_tests/tls/tls_client_cert2.test.py b/tests/gold_tests/tls/tls_client_cert2.test.py index 1e6970e7462..4645c048483 100644 --- a/tests/gold_tests/tls/tls_client_cert2.test.py +++ b/tests/gold_tests/tls/tls_client_cert2.test.py @@ -86,7 +86,13 @@ 'proxy.config.ssl.client.verify.server.policy': 'PERMISSIVE', }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine('map /case1 https://127.0.0.1:{0}/'.format(server.Variables.SSL_Port)) ts.Disk.remap_config.AddLine('map /case2 https://127.0.0.1:{0}/'.format(server2.Variables.SSL_Port)) diff --git a/tests/gold_tests/tls/tls_client_cert2_plugin.test.py b/tests/gold_tests/tls/tls_client_cert2_plugin.test.py index 3f7924d7773..c3dade36eb8 100644 --- a/tests/gold_tests/tls/tls_client_cert2_plugin.test.py +++ b/tests/gold_tests/tls/tls_client_cert2_plugin.test.py @@ -95,7 +95,13 @@ 'proxy.config.url_remap.pristine_host_hdr': 1, }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine('map /case1 https://127.0.0.1:{0}/'.format(server.Variables.SSL_Port)) ts.Disk.remap_config.AddLine('map /case2 https://127.0.0.1:{0}/'.format(server2.Variables.SSL_Port)) diff --git a/tests/gold_tests/tls/tls_client_cert_override.test.py b/tests/gold_tests/tls/tls_client_cert_override.test.py index 38f951d5705..466eaf9eba2 100644 --- a/tests/gold_tests/tls/tls_client_cert_override.test.py +++ b/tests/gold_tests/tls/tls_client_cert_override.test.py @@ -88,7 +88,13 @@ 'proxy.config.ssl.client.verify.server.policy': 'PERMISSIVE', }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map /case1 https://127.0.0.1:{0}/ @plugin=conf_remap.so @pparam=proxy.config.ssl.client.cert.filename={1} plugin=conf_remap.so @pparam=proxy.config.ssl.client.private_key.filename={2}' diff --git a/tests/gold_tests/tls/tls_client_cert_override_plugin.test.py b/tests/gold_tests/tls/tls_client_cert_override_plugin.test.py index c9af9e2cca3..3b7b8a47d0e 100644 --- a/tests/gold_tests/tls/tls_client_cert_override_plugin.test.py +++ b/tests/gold_tests/tls/tls_client_cert_override_plugin.test.py @@ -107,7 +107,13 @@ 'proxy.config.diags.debug.tags': 'ssl_secret_load|http|ssl', }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map /case1 https://127.0.0.1:{0}/ @plugin=conf_remap.so @pparam=proxy.config.ssl.client.cert.filename={1} plugin=conf_remap.so @pparam=proxy.config.ssl.client.private_key.filename={2}' diff --git a/tests/gold_tests/tls/tls_client_cert_plugin.test.py b/tests/gold_tests/tls/tls_client_cert_plugin.test.py index 7b8d39d91ee..98c9c6caae6 100644 --- a/tests/gold_tests/tls/tls_client_cert_plugin.test.py +++ b/tests/gold_tests/tls/tls_client_cert_plugin.test.py @@ -98,7 +98,13 @@ 'proxy.config.url_remap.pristine_host_hdr': 1, }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine('map /case1 https://127.0.0.1:{0}/'.format(server.Variables.SSL_Port)) ts.Disk.remap_config.AddLine('map /case2 https://127.0.0.1:{0}/'.format(server2.Variables.SSL_Port)) diff --git a/tests/gold_tests/tls/tls_client_verify.test.py b/tests/gold_tests/tls/tls_client_verify.test.py index 917e48842a8..710a2353eae 100644 --- a/tests/gold_tests/tls/tls_client_verify.test.py +++ b/tests/gold_tests/tls/tls_client_verify.test.py @@ -49,7 +49,13 @@ 'proxy.config.ssl.TLSv1_3.enabled': 0 }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Just map everything through to origin. This test is concentrating on the user-agent side ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}/'.format(server.Variables.Port)) diff --git a/tests/gold_tests/tls/tls_client_verify2.test.py b/tests/gold_tests/tls/tls_client_verify2.test.py index 657d8ebe05f..d8b00d36d93 100644 --- a/tests/gold_tests/tls/tls_client_verify2.test.py +++ b/tests/gold_tests/tls/tls_client_verify2.test.py @@ -48,7 +48,13 @@ 'proxy.config.ssl.CA.cert.filename': '{0}/signer.pem'.format(ts.Variables.SSLDir) }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Just map everything through to origin. This test is concentrating on the user-agent side ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}/'.format(server.Variables.Port)) diff --git a/tests/gold_tests/tls/tls_client_verify3.test.py b/tests/gold_tests/tls/tls_client_verify3.test.py index 27fd741b8f5..acda0e1cb2e 100644 --- a/tests/gold_tests/tls/tls_client_verify3.test.py +++ b/tests/gold_tests/tls/tls_client_verify3.test.py @@ -50,8 +50,19 @@ 'proxy.config.ssl.TLSv1_3.enabled': 0 }) -ts.Disk.ssl_multicert_config.AddLine('ssl_cert_name=bbb-signed.pem ssl_key_name=bbb-signed.key') -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - ssl_cert_name: bbb-signed.pem + ssl_key_name: bbb-signed.key +""".split("\n")) +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Just map everything through to origin. This test is concentrating on the user-agent side. ts.Disk.remap_config.AddLine(f'map / http://127.0.0.1:{server.Variables.Port}/') diff --git a/tests/gold_tests/tls/tls_client_versions.test.py b/tests/gold_tests/tls/tls_client_versions.test.py index fcd53c265e4..e24f027bbd0 100644 --- a/tests/gold_tests/tls/tls_client_versions.test.py +++ b/tests/gold_tests/tls/tls_client_versions.test.py @@ -40,7 +40,13 @@ # Need no remap rules. Everything should be processed by sni # Make sure the TS server certs are different from the origin certs -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) cipher_suite = 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2' if Condition.HasOpenSSLVersion("3.0.0"): diff --git a/tests/gold_tests/tls/tls_client_versions_minmax.test.py b/tests/gold_tests/tls/tls_client_versions_minmax.test.py index 2ea78535803..915f519a62c 100644 --- a/tests/gold_tests/tls/tls_client_versions_minmax.test.py +++ b/tests/gold_tests/tls/tls_client_versions_minmax.test.py @@ -40,7 +40,13 @@ # Need no remap rules. Everything should be processed by sni # Make sure the TS server certs are different from the origin certs -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { diff --git a/tests/gold_tests/tls/tls_engine.test.py b/tests/gold_tests/tls/tls_engine.test.py index 623f4305389..eadc8e87c76 100644 --- a/tests/gold_tests/tls/tls_engine.test.py +++ b/tests/gold_tests/tls/tls_engine.test.py @@ -55,7 +55,13 @@ ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir), diff --git a/tests/gold_tests/tls/tls_forward_nonhttp.test.py b/tests/gold_tests/tls/tls_forward_nonhttp.test.py index e2ba698ede0..23c6846438b 100644 --- a/tests/gold_tests/tls/tls_forward_nonhttp.test.py +++ b/tests/gold_tests/tls/tls_forward_nonhttp.test.py @@ -38,7 +38,13 @@ # Need no remap rules. Everything should be processed by sni # Make sure the TS server certs are different from the origin certs -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_hooks_client_verify.test.py b/tests/gold_tests/tls/tls_hooks_client_verify.test.py index f25e80b4890..33c8b21ec81 100644 --- a/tests/gold_tests/tls/tls_hooks_client_verify.test.py +++ b/tests/gold_tests/tls/tls_hooks_client_verify.test.py @@ -48,7 +48,13 @@ 'proxy.config.url_remap.pristine_host_hdr': 1 }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://foo.com:{1}/ https://127.0.0.1:{0}'.format(server.Variables.SSL_Port, ts.Variables.ssl_port)) diff --git a/tests/gold_tests/tls/tls_hooks_verify.test.py b/tests/gold_tests/tls/tls_hooks_verify.test.py index dd33443f05d..8507e55e59c 100644 --- a/tests/gold_tests/tls/tls_hooks_verify.test.py +++ b/tests/gold_tests/tls/tls_hooks_verify.test.py @@ -44,7 +44,13 @@ 'proxy.config.url_remap.pristine_host_hdr': 1 }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://foo.com:{1}/ https://127.0.0.1:{0}'.format(server.Variables.SSL_Port, ts.Variables.ssl_port)) diff --git a/tests/gold_tests/tls/tls_keepalive.test.py b/tests/gold_tests/tls/tls_keepalive.test.py index 3022e4f0594..7e393ed2260 100644 --- a/tests/gold_tests/tls/tls_keepalive.test.py +++ b/tests/gold_tests/tls/tls_keepalive.test.py @@ -44,7 +44,13 @@ 'proxy.config.log.max_secs_per_buffer': 1 }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) diff --git a/tests/gold_tests/tls/tls_ocsp.test.py b/tests/gold_tests/tls/tls_ocsp.test.py index 5a77f84aa97..8585b35f006 100644 --- a/tests/gold_tests/tls/tls_ocsp.test.py +++ b/tests/gold_tests/tls/tls_ocsp.test.py @@ -42,8 +42,20 @@ ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine( - 'dest_ip=* ssl_cert_name=server.ocsp.pem ssl_key_name=server.ocsp.key ssl_ocsp_name=ocsp_response.der') +ts.Disk.ssl_multicert_yaml.AddLines( + """ + + +ssl_multicert: + + + - dest_ip: "*" + ssl_cert_name: server.ocsp.pem + ssl_key_name: server.ocsp.key + ssl_ocsp_name: ocsp_response.der + + +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_origin_session_reuse.test.py b/tests/gold_tests/tls/tls_origin_session_reuse.test.py index 2763584b2f5..6889535c7b3 100644 --- a/tests/gold_tests/tls/tls_origin_session_reuse.test.py +++ b/tests/gold_tests/tls/tls_origin_session_reuse.test.py @@ -53,10 +53,34 @@ ts3.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) ts4.Disk.remap_config.AddLine('map / https://127.0.0.1:{0}'.format(ts3.Variables.ssl_port)) -ts1.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') -ts2.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') -ts3.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') -ts4.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts1.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) +ts2.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) +ts3.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) +ts4.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts1.Disk.records_config.update( { diff --git a/tests/gold_tests/tls/tls_partial_blind_tunnel.test.py b/tests/gold_tests/tls/tls_partial_blind_tunnel.test.py index eab7b9fca10..2a9dee38aa1 100644 --- a/tests/gold_tests/tls/tls_partial_blind_tunnel.test.py +++ b/tests/gold_tests/tls/tls_partial_blind_tunnel.test.py @@ -36,7 +36,13 @@ # Need no remap rules. Everything should be processed by sni # Make sure the TS server certs are different from the origin certs -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=signed-foo.pem ssl_key_name=signed-foo.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: signed-foo.pem + ssl_key_name: signed-foo.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_session_key_logging.test.py b/tests/gold_tests/tls/tls_session_key_logging.test.py index 7ace4a076aa..ecb269d6d6a 100644 --- a/tests/gold_tests/tls/tls_session_key_logging.test.py +++ b/tests/gold_tests/tls/tls_session_key_logging.test.py @@ -55,7 +55,13 @@ def setupTS(self, enable_secrets_logging): 'proxy.config.diags.debug.enabled': 1, 'proxy.config.diags.debug.tags': 'ssl_keylog' }) - self.ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + self.ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self.ts.Disk.remap_config.AddLine(f'map / https://127.0.0.1:{self.server.Variables.https_port}') keylog_file = os.path.join(self.ts.Variables.LOGDIR, "tls_secrets.txt") diff --git a/tests/gold_tests/tls/tls_session_reuse.test.py b/tests/gold_tests/tls/tls_session_reuse.test.py index 6647b169bb0..c66e2bcc1d3 100644 --- a/tests/gold_tests/tls/tls_session_reuse.test.py +++ b/tests/gold_tests/tls/tls_session_reuse.test.py @@ -42,8 +42,20 @@ ts1.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) ts2.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts1.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') -ts2.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts1.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) +ts2.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts1.Disk.records_config.update( { diff --git a/tests/gold_tests/tls/tls_sni_groups.test.py b/tests/gold_tests/tls/tls_sni_groups.test.py index 16c1cce280a..79e9b208288 100644 --- a/tests/gold_tests/tls/tls_sni_groups.test.py +++ b/tests/gold_tests/tls/tls_sni_groups.test.py @@ -37,7 +37,13 @@ # Need no remap rules. Everything should be processed by sni # Make sure the TS server certs are different from the origin certs -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { diff --git a/tests/gold_tests/tls/tls_sni_host_policy.test.py b/tests/gold_tests/tls/tls_sni_host_policy.test.py index 03a6e172c0b..bf7386bbf8e 100644 --- a/tests/gold_tests/tls/tls_sni_host_policy.test.py +++ b/tests/gold_tests/tls/tls_sni_host_policy.test.py @@ -52,7 +52,13 @@ 'proxy.config.diags.debug.tags': 'ssl', }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Just map everything through to origin. This test is concentrating on the user-agent side ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}/'.format(server.Variables.Port)) diff --git a/tests/gold_tests/tls/tls_sni_ip_allow.test.py b/tests/gold_tests/tls/tls_sni_ip_allow.test.py index 84cb9f6b9f3..fa23342639e 100644 --- a/tests/gold_tests/tls/tls_sni_ip_allow.test.py +++ b/tests/gold_tests/tls/tls_sni_ip_allow.test.py @@ -121,7 +121,13 @@ def _configure_trafficserver(self, tr: 'TestRun', connect_type: int, dns: 'Proce ' ip_allow: 1.2.3.4', ]) ts.addDefaultSSLFiles() - ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') + ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine(f'map / http://remapped.backend.server.com:{server.Variables.http_port}/') ts.Disk.records_config.update( { diff --git a/tests/gold_tests/tls/tls_sni_with_port.test.py b/tests/gold_tests/tls/tls_sni_with_port.test.py index 3f107d6765a..cadda0c677b 100644 --- a/tests/gold_tests/tls/tls_sni_with_port.test.py +++ b/tests/gold_tests/tls/tls_sni_with_port.test.py @@ -134,7 +134,13 @@ def _configure_traffic_server(self, tr: "TestRun", server_one: "Process", server f" tunnel_route: localhost:{server_two.Variables.https_port}", ]) - ts.Disk.ssl_multicert_config.AddLine(f"dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key") + ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) self._ts = ts diff --git a/tests/gold_tests/tls/tls_sni_yaml_reload.test.py b/tests/gold_tests/tls/tls_sni_yaml_reload.test.py index 8e2e0b2772b..133ecaf8964 100644 --- a/tests/gold_tests/tls/tls_sni_yaml_reload.test.py +++ b/tests/gold_tests/tls/tls_sni_yaml_reload.test.py @@ -45,9 +45,21 @@ ts.Disk.remap_config.AddLine(f'map / http://127.0.0.1:{server.Variables.Port}') -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.sni_yaml.AddLines( f""" diff --git a/tests/gold_tests/tls/tls_ticket.test.py b/tests/gold_tests/tls/tls_ticket.test.py index d49421b219c..d7e2df1858b 100644 --- a/tests/gold_tests/tls/tls_ticket.test.py +++ b/tests/gold_tests/tls/tls_ticket.test.py @@ -41,8 +41,20 @@ ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) ts2.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(server.Variables.Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') -ts2.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) +ts2.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.records_config.update( { diff --git a/tests/gold_tests/tls/tls_tunnel.test.py b/tests/gold_tests/tls/tls_tunnel.test.py index e2de6524af6..ab020181112 100644 --- a/tests/gold_tests/tls/tls_tunnel.test.py +++ b/tests/gold_tests/tls/tls_tunnel.test.py @@ -74,7 +74,13 @@ # Need no remap rules. Everything should be processed by sni # Make sure the TS server certs are different from the origin certs -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=signed-foo.pem ssl_key_name=signed-foo.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: signed-foo.pem + ssl_key_name: signed-foo.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_tunnel_forward.test.py b/tests/gold_tests/tls/tls_tunnel_forward.test.py index 472797d10ae..dc9e4a427ae 100644 --- a/tests/gold_tests/tls/tls_tunnel_forward.test.py +++ b/tests/gold_tests/tls/tls_tunnel_forward.test.py @@ -54,7 +54,13 @@ # Need no remap rules. Everything should be processed by sni # Make sure the TS server certs are different from the origin certs -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=signed-foo.pem ssl_key_name=signed-foo.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: signed-foo.pem + ssl_key_name: signed-foo.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_verify.test.py b/tests/gold_tests/tls/tls_verify.test.py index 64b32407f20..890bae18ce6 100644 --- a/tests/gold_tests/tls/tls_verify.test.py +++ b/tests/gold_tests/tls/tls_verify.test.py @@ -76,7 +76,13 @@ ts.Disk.remap_config.AddLine('map https://foo.wild.com/ https://127.0.0.1:{0}'.format(server_wild.Variables.SSL_Port)) ts.Disk.remap_config.AddLine('map https://foo_bar.wild.com/ https://127.0.0.1:{0}'.format(server_wild.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_verify2.test.py b/tests/gold_tests/tls/tls_verify2.test.py index db54aebba9d..72f261eab0e 100644 --- a/tests/gold_tests/tls/tls_verify2.test.py +++ b/tests/gold_tests/tls/tls_verify2.test.py @@ -64,7 +64,13 @@ ts.Disk.remap_config.AddLine('map https://bad_bar.com/ https://127.0.0.1:{0}'.format(server_bar.Variables.SSL_Port)) ts.Disk.remap_config.AddLine('map / https://127.0.0.1:{0}'.format(server.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_verify3.test.py b/tests/gold_tests/tls/tls_verify3.test.py index 08920ffc70c..0603499aa34 100644 --- a/tests/gold_tests/tls/tls_verify3.test.py +++ b/tests/gold_tests/tls/tls_verify3.test.py @@ -68,7 +68,13 @@ 'map https://bob.bar.com:{1}/ https://127.0.0.1:{0}'.format(server_bar.Variables.SSL_Port, ts.Variables.ssl_port)) ts.Disk.remap_config.AddLine('map / https://127.0.0.1:{0}'.format(server.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_verify4.test.py b/tests/gold_tests/tls/tls_verify4.test.py index bab09093229..437d582bd58 100644 --- a/tests/gold_tests/tls/tls_verify4.test.py +++ b/tests/gold_tests/tls/tls_verify4.test.py @@ -65,7 +65,13 @@ ts.Disk.remap_config.AddLine('map https://bad_bar.com/ https://127.0.0.1:{0}'.format(server_bar.Variables.SSL_Port)) ts.Disk.remap_config.AddLine('map / https://127.0.0.1:{0}'.format(server.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_verify_base.test.py b/tests/gold_tests/tls/tls_verify_base.test.py index 7526cfa2dc0..7617bee1c14 100644 --- a/tests/gold_tests/tls/tls_verify_base.test.py +++ b/tests/gold_tests/tls/tls_verify_base.test.py @@ -64,7 +64,13 @@ ts.Disk.remap_config.AddLine('map https://bar.com/ https://127.0.0.1:{0}'.format(server_bar.Variables.SSL_Port)) ts.Disk.remap_config.AddLine('map https://bad_bar.com/ https://127.0.0.1:{0}'.format(server_bar.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_verify_ca_override.test.py b/tests/gold_tests/tls/tls_verify_ca_override.test.py index 2de7f424d79..610bc016031 100644 --- a/tests/gold_tests/tls/tls_verify_ca_override.test.py +++ b/tests/gold_tests/tls/tls_verify_ca_override.test.py @@ -71,7 +71,13 @@ 'map /badcase2 https://127.0.0.1:{0}/ @plugin=conf_remap.so @pparam=proxy.config.ssl.client.CA.cert.filename={1}/{2}'.format( server2.Variables.SSL_Port, ts.Variables.SSLDir, "signer.pem")) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_verify_not_pristine.test.py b/tests/gold_tests/tls/tls_verify_not_pristine.test.py index 2429f256208..2d7723d7038 100644 --- a/tests/gold_tests/tls/tls_verify_not_pristine.test.py +++ b/tests/gold_tests/tls/tls_verify_not_pristine.test.py @@ -53,7 +53,13 @@ ts.Disk.remap_config.AddLine( 'map https://foo.com:{0}/ https://bar.com:{1}'.format(ts.Variables.ssl_port, server_foo.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_verify_override.test.py b/tests/gold_tests/tls/tls_verify_override.test.py index 747a4d804cd..5fc323da3cf 100644 --- a/tests/gold_tests/tls/tls_verify_override.test.py +++ b/tests/gold_tests/tls/tls_verify_override.test.py @@ -101,7 +101,13 @@ 'map /snipolicybarhost https://bar.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.properties=NAME @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED @plugin=conf_remap.so @pparam=proxy.config.ssl.client.sni_policy=host' .format(server_bar.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_verify_override_base.test.py b/tests/gold_tests/tls/tls_verify_override_base.test.py index be8179ddacf..ab07dbaeed8 100644 --- a/tests/gold_tests/tls/tls_verify_override_base.test.py +++ b/tests/gold_tests/tls/tls_verify_override_base.test.py @@ -100,7 +100,13 @@ 'map /snipolicybarservername https://bar.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.properties=NAME @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED @plugin=conf_remap.so @pparam=proxy.config.ssl.client.sni_policy=server_name' .format(server_bar.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # Case 1, global config policy=permissive properties=signature # override for foo.com policy=enforced properties=all diff --git a/tests/gold_tests/tls/tls_verify_override_sni.test.py b/tests/gold_tests/tls/tls_verify_override_sni.test.py index 97391eb876d..f671d44bd5e 100644 --- a/tests/gold_tests/tls/tls_verify_override_sni.test.py +++ b/tests/gold_tests/tls/tls_verify_override_sni.test.py @@ -83,7 +83,13 @@ 'map http://foo.com/overrideproperties https://bar.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.properties=SIGNATURE' .format(server_foo.Variables.SSL_Port)) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) # global config policy=permissive properties=all ts.Disk.records_config.update( diff --git a/tests/gold_tests/tls_hooks/tls_hooks.test.py b/tests/gold_tests/tls_hooks/tls_hooks.test.py index ffb20503269..db73db2a786 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks.test.py @@ -43,7 +43,13 @@ 'proxy.config.ssl.TLSv1_3.enabled': 0, }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks10.test.py b/tests/gold_tests/tls_hooks/tls_hooks10.test.py index fb52206ed28..0c32f87d231 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks10.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks10.test.py @@ -41,7 +41,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks11.test.py b/tests/gold_tests/tls_hooks/tls_hooks11.test.py index f92b7dc5931..2c5a6b72d3f 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks11.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks11.test.py @@ -42,7 +42,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks12.test.py b/tests/gold_tests/tls_hooks/tls_hooks12.test.py index 78f369691f7..aed35b57768 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks12.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks12.test.py @@ -41,7 +41,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks13.test.py b/tests/gold_tests/tls_hooks/tls_hooks13.test.py index d9820afe05d..515fd584936 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks13.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks13.test.py @@ -41,7 +41,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} https://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.SSL_Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks14.test.py b/tests/gold_tests/tls_hooks/tls_hooks14.test.py index 8364fac306b..4128b58497c 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks14.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks14.test.py @@ -42,7 +42,13 @@ 'proxy.config.ssl.client.verify.server.policy': 'PERMISSIVE', }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} https://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.SSL_Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks15.test.py b/tests/gold_tests/tls_hooks/tls_hooks15.test.py index fd2aa270b5c..e43a26f883a 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks15.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks15.test.py @@ -41,7 +41,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} https://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.SSL_Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks16.test.py b/tests/gold_tests/tls_hooks/tls_hooks16.test.py index 78042926341..9a8a083be88 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks16.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks16.test.py @@ -44,7 +44,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{1} http://127.0.0.1:{0}'.format(server.Variables.Port, ts.Variables.ssl_port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks17.test.py b/tests/gold_tests/tls_hooks/tls_hooks17.test.py index 34a48e98d96..0b54d7a9e45 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks17.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks17.test.py @@ -44,7 +44,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{1} http://127.0.0.1:{0}'.format(server.Variables.Port, ts.Variables.ssl_port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks18.test.py b/tests/gold_tests/tls_hooks/tls_hooks18.test.py index 64e7b3b089a..c7e03faeb6d 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks18.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks18.test.py @@ -44,7 +44,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{1} http://127.0.0.1:{0}'.format(server.Variables.Port, ts.Variables.ssl_port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks2.test.py b/tests/gold_tests/tls_hooks/tls_hooks2.test.py index 66afffac595..0323002f1c9 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks2.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks2.test.py @@ -42,7 +42,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks3.test.py b/tests/gold_tests/tls_hooks/tls_hooks3.test.py index 006eecb479f..23aeaa9797b 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks3.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks3.test.py @@ -42,7 +42,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks4.test.py b/tests/gold_tests/tls_hooks/tls_hooks4.test.py index f7e0742baaf..7068c838e4f 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks4.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks4.test.py @@ -42,7 +42,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks6.test.py b/tests/gold_tests/tls_hooks/tls_hooks6.test.py index 8e943fd3a99..1b2635f4349 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks6.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks6.test.py @@ -42,7 +42,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks7.test.py b/tests/gold_tests/tls_hooks/tls_hooks7.test.py index 29a4490e281..e664b717daa 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks7.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks7.test.py @@ -42,7 +42,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks8.test.py b/tests/gold_tests/tls_hooks/tls_hooks8.test.py index 721ce3630b4..be08cc17371 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks8.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks8.test.py @@ -42,7 +42,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) diff --git a/tests/gold_tests/tls_hooks/tls_hooks9.test.py b/tests/gold_tests/tls_hooks/tls_hooks9.test.py index cf77135203d..343c29f54ae 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks9.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks9.test.py @@ -42,7 +42,13 @@ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://example.com:{0} http://127.0.0.1:{1}'.format(ts.Variables.ssl_port, server.Variables.Port)) diff --git a/tests/gold_tests/traffic_ctl/convert_ssl_multicert/convert_ssl_multicert.test.py b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/convert_ssl_multicert.test.py new file mode 100644 index 00000000000..c0ffbcfb1d8 --- /dev/null +++ b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/convert_ssl_multicert.test.py @@ -0,0 +1,60 @@ +''' +Test the traffic_ctl config convert ssl_multicert command. +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Test.Summary = 'Test traffic_ctl config convert ssl_multicert command.' + +# Create an ATS process to get the environment with PATH set correctly. +ts = Test.MakeATSProcess("ts", enable_cache=False) + +# Test 1: Basic config conversion. +tr = Test.AddTestRun("Test basic ssl_multicert.config conversion") +tr.Setup.Copy('legacy_config/basic.config') +tr.Processes.Default.Command = 'traffic_ctl config convert ssl_multicert basic.config -' +tr.Processes.Default.Streams.stdout = "gold/basic.yaml" +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.Env = ts.Env +tr.Processes.Default.StartBefore(ts) +tr.StillRunningAfter = ts + +# Test 2: Full config with all options. +tr = Test.AddTestRun("Test full ssl_multicert.config conversion with all options") +tr.Setup.Copy('legacy_config/full.config') +tr.Processes.Default.Command = 'traffic_ctl config convert ssl_multicert full.config -' +tr.Processes.Default.Streams.stdout = "gold/full.yaml" +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.Env = ts.Env +tr.StillRunningAfter = ts + +# Test 3: Config with quoted values. +tr = Test.AddTestRun("Test ssl_multicert.config with quoted values") +tr.Setup.Copy('legacy_config/quoted.config') +tr.Processes.Default.Command = 'traffic_ctl config convert ssl_multicert quoted.config -' +tr.Processes.Default.Streams.stdout = "gold/quoted.yaml" +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.Env = ts.Env +tr.StillRunningAfter = ts + +# Test 4: Output to file. +tr = Test.AddTestRun("Test output to file") +tr.Setup.Copy('legacy_config/basic.config') +tr.Processes.Default.Command = 'traffic_ctl config convert ssl_multicert basic.config generated.yaml > /dev/null && cat generated.yaml' +tr.Processes.Default.Streams.stdout = "gold/basic.yaml" +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.Env = ts.Env +tr.StillRunningAfter = ts diff --git a/tests/gold_tests/traffic_ctl/convert_ssl_multicert/gold/basic.yaml b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/gold/basic.yaml new file mode 100644 index 00000000000..8cd4076bee3 --- /dev/null +++ b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/gold/basic.yaml @@ -0,0 +1,6 @@ +ssl_multicert: + - ssl_cert_name: server.pem + dest_ip: "*" + ssl_key_name: server.key + - ssl_cert_name: example.pem + dest_ip: 192.168.1.1 diff --git a/tests/gold_tests/traffic_ctl/convert_ssl_multicert/gold/full.yaml b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/gold/full.yaml new file mode 100644 index 00000000000..917ad6297e0 --- /dev/null +++ b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/gold/full.yaml @@ -0,0 +1,20 @@ +ssl_multicert: + - ssl_cert_name: server.pem + dest_ip: "*" + ssl_key_name: server.key + ssl_ticket_enabled: 1 + ssl_ticket_number: 3 + - ssl_cert_name: ecdsa.pem,rsa.pem + dest_ip: 10.0.0.1:443 + ssl_key_name: ecdsa.key,rsa.key + ssl_ca_name: ca.pem + ssl_ocsp_name: ocsp.der + - ssl_cert_name: encrypted.pem + dest_ip: "*" + ssl_key_dialog: exec:/usr/bin/getpass foo + - dest_ip: 192.168.1.1 + action: tunnel + - ssl_cert_name: wildcard.pem + dest_ip: "*" + dest_fqdn: "*.example.com" + ssl_ticket_enabled: 0 diff --git a/tests/gold_tests/traffic_ctl/convert_ssl_multicert/gold/quoted.yaml b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/gold/quoted.yaml new file mode 100644 index 00000000000..0567cfca3cc --- /dev/null +++ b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/gold/quoted.yaml @@ -0,0 +1,6 @@ +ssl_multicert: + - ssl_cert_name: server.pem + dest_ip: "*" + ssl_key_dialog: exec:/usr/bin/getpass arg1 'arg 2' + - ssl_cert_name: another.pem + dest_ip: "[::1]:8443" diff --git a/tests/gold_tests/traffic_ctl/convert_ssl_multicert/legacy_config/basic.config b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/legacy_config/basic.config new file mode 100644 index 00000000000..fb686c14704 --- /dev/null +++ b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/legacy_config/basic.config @@ -0,0 +1,3 @@ +# Basic ssl_multicert.config example +ssl_cert_name=server.pem ssl_key_name=server.key dest_ip=* +ssl_cert_name=example.pem dest_ip=192.168.1.1 diff --git a/tests/gold_tests/traffic_ctl/convert_ssl_multicert/legacy_config/full.config b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/legacy_config/full.config new file mode 100644 index 00000000000..b7cd4f504e3 --- /dev/null +++ b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/legacy_config/full.config @@ -0,0 +1,7 @@ +# Full ssl_multicert.config with all options +# This exercises all supported configuration keys +ssl_cert_name=server.pem ssl_key_name=server.key dest_ip=* ssl_ticket_enabled=1 ssl_ticket_number=3 +ssl_cert_name=ecdsa.pem,rsa.pem ssl_key_name=ecdsa.key,rsa.key dest_ip=10.0.0.1:443 ssl_ca_name=ca.pem ssl_ocsp_name=ocsp.der +ssl_cert_name=encrypted.pem ssl_key_dialog="exec:/usr/bin/getpass foo" +dest_ip=192.168.1.1 action=tunnel +ssl_cert_name=wildcard.pem dest_fqdn=*.example.com ssl_ticket_enabled=0 diff --git a/tests/gold_tests/traffic_ctl/convert_ssl_multicert/legacy_config/quoted.config b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/legacy_config/quoted.config new file mode 100644 index 00000000000..af1bb0923c7 --- /dev/null +++ b/tests/gold_tests/traffic_ctl/convert_ssl_multicert/legacy_config/quoted.config @@ -0,0 +1,3 @@ +# Config with quoted values +ssl_cert_name=server.pem ssl_key_dialog="exec:/usr/bin/getpass arg1 'arg 2'" +ssl_cert_name=another.pem dest_ip="[::1]:8443" diff --git a/tests/gold_tests/traffic_ctl/show_ssl_multicert/gold/show_json.gold b/tests/gold_tests/traffic_ctl/show_ssl_multicert/gold/show_json.gold new file mode 100644 index 00000000000..5fff803226e --- /dev/null +++ b/tests/gold_tests/traffic_ctl/show_ssl_multicert/gold/show_json.gold @@ -0,0 +1 @@ +{"ssl_multicert": [{"ssl_cert_name": "server.pem", "dest_ip": "*", "ssl_key_name": "server.key"}]} diff --git a/tests/gold_tests/traffic_ctl/show_ssl_multicert/gold/show_yaml.gold b/tests/gold_tests/traffic_ctl/show_ssl_multicert/gold/show_yaml.gold new file mode 100644 index 00000000000..5c558469ae2 --- /dev/null +++ b/tests/gold_tests/traffic_ctl/show_ssl_multicert/gold/show_yaml.gold @@ -0,0 +1,4 @@ +ssl_multicert: + - ssl_cert_name: server.pem + dest_ip: "*" + ssl_key_name: server.key diff --git a/tests/gold_tests/traffic_ctl/show_ssl_multicert/show_ssl_multicert.test.py b/tests/gold_tests/traffic_ctl/show_ssl_multicert/show_ssl_multicert.test.py new file mode 100644 index 00000000000..984df9b7f18 --- /dev/null +++ b/tests/gold_tests/traffic_ctl/show_ssl_multicert/show_ssl_multicert.test.py @@ -0,0 +1,91 @@ +''' +Test the traffic_ctl config ssl-multicert show command. +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Test.Summary = 'Test traffic_ctl config ssl-multicert show command.' + + +class ShowSSLMulticert: + + def __init__(self): + self.setup_ts() + self.setup_show_default() + self.setup_show_json() + self.setup_show_yaml() + + def setup_ts(self): + self._ts = Test.MakeATSProcess("ts", enable_cache=False, enable_tls=True) + self._ts.addDefaultSSLFiles() + self._ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - ssl_cert_name: server.pem + dest_ip: "*" + ssl_key_name: server.key +""".split("\n")) + self._ts.Disk.records_config.update( + { + 'proxy.config.ssl.server.cert.path': f'{self._ts.Variables.SSLDir}', + 'proxy.config.ssl.server.private_key.path': f'{self._ts.Variables.SSLDir}', + }) + + def setup_show_default(self): + tr = Test.AddTestRun("Test ssl-multicert show (default YAML format)") + tr.Processes.Default.Command = 'traffic_ctl config ssl-multicert show' + tr.Processes.Default.Streams.stdout = "gold/show_yaml.gold" + tr.Processes.Default.ReturnCode = 0 + tr.Processes.Default.Env = self._ts.Env + tr.Processes.Default.StartBefore(self._ts) + tr.StillRunningAfter = self._ts + + def setup_show_json(self): + # Test with explicit --json flag. + tr = Test.AddTestRun("Test ssl-multicert show --json") + tr.Processes.Default.Command = 'traffic_ctl config ssl-multicert show --json' + tr.Processes.Default.Streams.stdout = "gold/show_json.gold" + tr.Processes.Default.ReturnCode = 0 + tr.Processes.Default.Env = self._ts.Env + tr.StillRunningAfter = self._ts + + # Test with short -j flag. + tr = Test.AddTestRun("Test ssl-multicert show -j") + tr.Processes.Default.Command = 'traffic_ctl config ssl-multicert show -j' + tr.Processes.Default.Streams.stdout = "gold/show_json.gold" + tr.Processes.Default.ReturnCode = 0 + tr.Processes.Default.Env = self._ts.Env + tr.StillRunningAfter = self._ts + + def setup_show_yaml(self): + # Test with --yaml flag. + tr = Test.AddTestRun("Test ssl-multicert show --yaml") + tr.Processes.Default.Command = 'traffic_ctl config ssl-multicert show --yaml' + tr.Processes.Default.Streams.stdout = "gold/show_yaml.gold" + tr.Processes.Default.ReturnCode = 0 + tr.Processes.Default.Env = self._ts.Env + tr.StillRunningAfter = self._ts + + # Test with short -y flag. + tr = Test.AddTestRun("Test ssl-multicert show -y") + tr.Processes.Default.Command = 'traffic_ctl config ssl-multicert show -y' + tr.Processes.Default.Streams.stdout = "gold/show_yaml.gold" + tr.Processes.Default.ReturnCode = 0 + tr.Processes.Default.Env = self._ts.Env + tr.StillRunningAfter = self._ts + + +ShowSSLMulticert() diff --git a/tests/gold_tests/tunnel/tunnel_transform.test.py b/tests/gold_tests/tunnel/tunnel_transform.test.py index dabb0692b44..ed169c453f8 100644 --- a/tests/gold_tests/tunnel/tunnel_transform.test.py +++ b/tests/gold_tests/tunnel/tunnel_transform.test.py @@ -58,7 +58,13 @@ 'proxy.config.http.connect_ports': '{0}'.format(server.Variables.SSL_Port) }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.sni_yaml.AddLines([ 'sni:', diff --git a/tests/gold_tests/tunnel/txn_type.test.py b/tests/gold_tests/tunnel/txn_type.test.py index 8c79e0a6798..a52933f5ca1 100644 --- a/tests/gold_tests/tunnel/txn_type.test.py +++ b/tests/gold_tests/tunnel/txn_type.test.py @@ -63,7 +63,13 @@ 'proxy.config.http.connect_ports': '{0}'.format(server.Variables.SSL_Port) }) -ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') +ts.Disk.ssl_multicert_yaml.AddLines( + """ +ssl_multicert: + - dest_ip: "*" + ssl_cert_name: server.pem + ssl_key_name: server.key +""".split("\n")) ts.Disk.remap_config.AddLine( 'map https://http-test:{0}/ https://127.0.0.1:{1}/'.format(ts.Variables.ssl_port, server.Variables.SSL_Port))