Skip to content

Ability to pass along attributes via SslContext #6542

@rkapsi

Description

@rkapsi

This is related to the #6158 OCSP pull request.

The #6158 PR is demonstrating the most simple way of obtaining and dealing with OCSP stapling but it gets a bit more complicated in practice. In particular when you look at how SniHandler and AsyncMapping work (which we use).

  1. AsyncMapping returns Future<SslContext>
  2. SniHandler uses Future<SslContext> to construct SslEngine + SslHandler

... but how do I pass along the info that is needed to obtain a staple or the OCSP staple itself? I'm currently using the delegate pattern around SslContext but it gets quickly rather messy and error prone in conjunction with reference counting. It'd be great if it was possible to pass along arbitrary attributes via SslContext (e.g. via AttributeMap or simply as a Map<Object, Object>).

A more general way of looking at is the desire to pass configuration parameters from SslContext to "things" that use it. One scenario is described above but other use-cases could be other config parameters for the SslEngine such as setEnabledProtocols() or some custom behavior for the SslHandler etc etc.

Here's some pseudo code to illustrate it. WDYT - happy to PR it.

public class MySniHandler extends SniHandler {

  public static final AttributeKey<OcspKey> OCSP_KEY = AttributeKey.valueOf(OcspKey.class, "OCSP_KEY");
  
  public static final AttributeKey<String[]> PROTOCOLS_KEY = AttributeKey.valueOf(String[].class, "PROTOCOLS_KEY");
  
  private final OcspCache<OcspKey, Future<byte[]>> ocspCache;
  
  public MySniHandler(AsyncMapping<String, SslContext> mapping, OcspCache<OcspKey, Future<byte[]>> ocspCache) {
    super(mapping);
    this.ocspCache = ocspCache;
  }

  @Override
  protected void replaceHandler(ChannelHandlerContext ctx, String hostname, SslContext sslContext) throws Exception {
    SslHandler sslHandler = sslContext.newHandler(ctx.alloc());
    ReferenceCountedOpenSslEngine engine = (ReferenceCountedOpenSslEngine) sslHandler.engine();
    
    OcspKey ocspKey = sslContext.attr(OCSP_KEY).get();
    
    // I (the server) may or may not have a staple and I don't want
    // to make the client wait for it.
    Future<byte[]> future = ocspCache.get(ocspKey);
    if (future.isSuccess()) {
      engine.setOcspResponse(future.getNow());
    }
    
    String[] protocols = sslContext.attr(PROTOCOLS_KEY).get();
    engine.setEnabledProtocols(protocols);
    
    ctx.pipeline().replace(this, SslHandler.class.getName(), sslHandler);
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions