...

Text file src/github.com/emissary-ingress/emissary/v3/python/ambassador/ir/irtls.py

Documentation: github.com/emissary-ingress/emissary/v3/python/ambassador/ir

     1# Copyright 2018 Datawire. All rights reserved.
     2#
     3# Licensed under the Apache License, Version 2.0 (the "License");
     4# you may not use this file except in compliance with the License.
     5# You may obtain a copy of the License at
     6#
     7#     http://www.apache.org/licenses/LICENSE-2.0
     8#
     9# Unless required by applicable law or agreed to in writing, software
    10# distributed under the License is distributed on an "AS IS" BASIS,
    11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12# See the License for the specific language governing permissions and
    13# limitations under the License
    14
    15from typing import TYPE_CHECKING
    16
    17from ..config import Config
    18from .irresource import IRResource as IRResource
    19from .irtlscontext import IRTLSContext
    20
    21if TYPE_CHECKING:
    22    from .ir import IR  # pragma: no cover
    23
    24
    25#############################################################################
    26## tls.py -- the tls_context configuration object for Ambassador
    27##
    28## IRAmbassadorTLS represents an Ambassador TLS configuration: it's the way
    29## we unify the TLS module and the 'tls' block in the Ambassador module. This
    30## class is pretty much all about managing priority between the two -- any
    31## important information here gets turned into IRTLSContext objects before
    32## TLS configuration actually happens.
    33##
    34## There's a fair amount of logic around making priority decisions between
    35## the 'tls' block and the TLS module at present. Probably that logic should
    36## migrate here, or this class should go away.
    37
    38
    39class IRAmbassadorTLS(IRResource):
    40    def __init__(
    41        self,
    42        ir: "IR",
    43        aconf: Config,
    44        rkey: str = "ir.tlsmodule",
    45        kind: str = "IRTLSModule",
    46        name: str = "ir.tlsmodule",
    47        enabled: bool = True,
    48        **kwargs
    49    ) -> None:
    50        """
    51        Initialize an IRAmbassadorTLS from the raw fields of its Resource.
    52        """
    53
    54        ir.logger.debug("IRAmbassadorTLS __init__ (%s %s %s)" % (kind, name, kwargs))
    55
    56        super().__init__(
    57            ir=ir, aconf=aconf, rkey=rkey, kind=kind, name=name, enabled=enabled, **kwargs
    58        )
    59
    60
    61class TLSModuleFactory:
    62    @classmethod
    63    def load_all(cls, ir: "IR", aconf: Config) -> None:
    64        assert ir
    65
    66        tls_module = aconf.get_module("tls")
    67
    68        if tls_module:
    69            # ir.logger.debug("TLSModuleFactory saving TLS module: %s" % tls_module.as_json())
    70
    71            # XXX What a hack. IRAmbassadorTLS.from_resource() should be able to make
    72            # this painless.
    73            new_args = dict(tls_module.as_dict())
    74            new_rkey = new_args.pop("rkey", tls_module.rkey)
    75            new_kind = new_args.pop("kind", tls_module.kind)
    76            new_name = new_args.pop("name", tls_module.name)
    77            new_location = new_args.pop("location", tls_module.location)
    78
    79            ir.tls_module = IRAmbassadorTLS(
    80                ir,
    81                aconf,
    82                rkey=new_rkey,
    83                kind=new_kind,
    84                name=new_name,
    85                location=new_location,
    86                **new_args
    87            )
    88
    89            ir.logger.debug("TLSModuleFactory saved TLS module: %s" % ir.tls_module.as_json())
    90
    91        # Next, a TLS module in the Ambassador module overrides any other TLS Module.
    92        amod = aconf.get_module("ambassador")
    93
    94        if amod:
    95            ir.ambassador_module.sourced_by(amod)
    96            ir.ambassador_module.referenced_by(amod)
    97
    98            amod_tls = amod.get("tls", None)
    99
   100            # Check for an Ambassador module tls field so that we can warn the user that this field is deprecated!
   101            if amod_tls:
   102                ir.post_error(
   103                    "The 'tls' field on the Ambassador module is deprecated! Please use a TLSContext instead https://www.getambassador.io/docs/edge-stack/latest/topics/running/tls/#tlscontext"
   104                )
   105
   106        # Finally, if we have a TLS Module, turn it into a TLSContext.
   107        if ir.tls_module:
   108            ir.logger.debug("TLSModuleFactory translating TLS module to TLSContext")
   109
   110            # Stash a sane rkey and location for contexts we create.
   111            ctx_rkey = ir.tls_module.get("rkey", ir.ambassador_module.rkey)
   112            ctx_location = ir.tls_module.get("location", ir.ambassador_module.location)
   113
   114            # The TLS module 'server' and 'client' blocks are actually a _single_ TLSContext
   115            # to Ambassador.
   116
   117            server = ir.tls_module.pop("server", None)
   118            client = ir.tls_module.pop("client", None)
   119
   120            if server and server.get("enabled", True):
   121                # We have a server half. Excellent.
   122
   123                ctx = IRTLSContext.from_legacy(
   124                    ir,
   125                    "server",
   126                    ctx_rkey,
   127                    ctx_location,
   128                    cert=server,
   129                    termination=True,
   130                    validation_ca=client,
   131                )
   132
   133                if ctx.is_active():
   134                    ir.save_tls_context(ctx)
   135
   136            # Other blocks in the TLS module weren't ever really documented, so I seriously doubt
   137            # that they're a factor... but, weirdly, we have a test for them...
   138
   139            for legacy_name, legacy_ctx in ir.tls_module.as_dict().items():
   140                if (
   141                    legacy_name.startswith("_")
   142                    or (legacy_name == "name")
   143                    or (legacy_name == "namespace")
   144                    or (legacy_name == "metadata_labels")
   145                    or (legacy_name == "location")
   146                    or (legacy_name == "kind")
   147                    or (legacy_name == "enabled")
   148                ):
   149                    continue
   150
   151                ctx = IRTLSContext.from_legacy(
   152                    ir,
   153                    legacy_name,
   154                    ctx_rkey,
   155                    ctx_location,
   156                    cert=legacy_ctx,
   157                    termination=False,
   158                    validation_ca=None,
   159                )
   160
   161                if ctx.is_active():
   162                    ir.save_tls_context(ctx)
   163
   164    @classmethod
   165    def finalize(cls, ir: "IR", aconf: Config) -> None:
   166        pass

View as plain text