F5Networks / f5-appsvcs-extension

F5 BIG-IP Application Services 3 Extension
Apache License 2.0
169 stars 54 forks source link

Can't use "requireSNI" property #871

Open GWilczek opened 2 months ago

GWilczek commented 2 months ago

Environment

Summary

The requirement is to configure multiple SNI profiles, while default one has set "requireSNI": true. This is needed for a use case where traffic that doesn't match to SNI (server name non exist or not match) is rejected:

https://clouddocs.f5.com/products/extensions/f5-appsvcs-extension/latest/refguide/schema-reference.html#tls-server

requireSNI (boolean) false true, false When a client sends no or unknown SNI and Require SNI is false (default), the system uses the primary certificate, otherwise the system rejects the client

Steps To Reproduce

Steps to reproduce the behavior:

  1. Submit the following declaration:
    
    {
    "$schema": "https://raw.githubusercontent.com/F5Networks/f5-appsvcs-extension/master/schema/latest/as3-schema.json",
    "class": "AS3",
    "action": "deploy",
    "declaration": {
        "class": "ADC",
        "schemaVersion": "3.40.0",
        "controls": {
            "class": "Controls",
            "trace": true,
            "logLevel": "debug",
            "traceResponse": true
        },
        "sni_tenant": {
            "class": "Tenant",
            "sni_app": {
                "class": "Application",
                "template": "https",
                "serviceMain": {
                    "class": "Service_HTTPS",
                    "profileHTTP": {"bigip": "/Common/http"},
                    "profileTCP": {"bigip": "/Common/tcp"},
                    "virtualAddresses": ["192.168.5.116"],
                    "virtualPort": 18443,
                    "redirect80": false,
                    "maxConnections": 0,
                    "mirroring": "none",
                    "shareAddresses": true,
                    "pool": "pool_1",
                    "serverTLS": "client_ssl_profile",
                    "clientTLS": {"bigip": "/Common/serverssl"},
                    "snat": "auto"
                },
                "client_ssl_profile": {
                    "class": "TLS_Server",
                    "certificates": [
                        {
                            "matchToSNI": "",
                            "certificate": "snidefault"
                        },
                        {
                            "matchToSNI": "https1.example.com",
                            "certificate": "sni1"
                        },
                        {
                            "matchToSNI": "https2.example.com",
                            "certificate": "sni2"
                        }
                    ],
                    "ciphers": "DEFAULT",
                    "requireSNI": true
                },
                "snidefault": {
                    "class": "Certificate",
                    "certificate": {
                        "bigip": "/Common/lab"
                    },
                    "privateKey": {
                        "bigip": "/Common/lab"
                    },
                    "chainCA": {
                        "bigip": "/Common/ca-bundle.crt"
                    }
                },
                "sni1": {
                    "class": "Certificate",
                    "certificate": {
                        "bigip": "/Common/lab"
                    },
                    "privateKey": {
                        "bigip": "/Common/lab"
                    },
                    "chainCA": {
                        "bigip": "/Common/ca-bundle.crt"
                    }
                },
                "sni2": {
                    "class": "Certificate",
                    "certificate": {
                        "bigip": "/Common/lab"
                    },
                    "privateKey": {
                        "bigip": "/Common/lab"
                    },
                    "chainCA": {
                        "bigip": "/Common/ca-bundle.crt"
                    }
                },
                "pool_1": {
                    "class": "Pool",
                    "loadBalancingMode": "least-connections-member",
                    "serviceDownAction": "reset",
                    "slowRampTime": 0,
                    "monitors": [
                        {
                            "bigip": "/Common/https"
                        }
                    ],
                    "members": [
                            {
                                "servicePort": 8080,
                                "serverAddresses": ["192.168.123.1", "192.168.123.2"],
                                "shareNodes": true
                            }
                        ]
                    }
            }
        }
    }
    }

2. Observe the following error response:
```json
        {
            "code": 422,
            "message": "declaration failed",
            "response": "0107150a:3: SNI require is enabled on clientssl/serverssl profile /sni_tenant/sni_app/client_ssl_profile-1- yet SNI default is not enabled.",
            "host": "localhost",
            "tenant": "sni_tenant",
            "runTime": 1774,
            "declarationId": "autogen_fc229ddb-7361-4789-8bb6-cf2e89273730"
        }

This works in TMSH if "requireSNI": false :

root@(bigip1)(cfg-sync In Sync)(Active)(/sni_tenant/sni_app)(tmos)# list ltm profile client-ssl client_ssl_profile sni-require
ltm profile client-ssl client_ssl_profile {
    sni-require false
}
root@(bigip1)(cfg-sync In Sync)(Active)(/sni_tenant/sni_app)(tmos)# modify ltm profile client-ssl client_ssl_profile sni-require true
root@(bigip1)(cfg-sync In Sync)(Active)(/sni_tenant/sni_app)(tmos)# list ltm profile client-ssl client_ssl_profile sni-require
ltm profile client-ssl client_ssl_profile {
    sni-require true
}

Expected Behavior

Allow default SNI profile set to require SNI, currently "requireSNI" seems to be propagated to all profiles automatically created based on "certificates": [] list which is incorrect behavior.

Actual Behavior

Declaration returns error, it works in TMSH/GUI but not using AS3