github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/ca/forward.go (about)

     1  package ca
     2  
     3  import (
     4  	"context"
     5  
     6  	"google.golang.org/grpc/metadata"
     7  	"google.golang.org/grpc/peer"
     8  )
     9  
    10  const (
    11  	certForwardedKey = "forwarded_cert"
    12  	certCNKey        = "forwarded_cert_cn"
    13  	certOUKey        = "forwarded_cert_ou"
    14  	certOrgKey       = "forwarded_cert_org"
    15  	remoteAddrKey    = "remote_addr"
    16  )
    17  
    18  // forwardedTLSInfoFromContext obtains forwarded TLS CN/OU from the grpc.MD
    19  // object in ctx.
    20  func forwardedTLSInfoFromContext(ctx context.Context) (remoteAddr string, cn string, org string, ous []string) {
    21  	md, _ := metadata.FromIncomingContext(ctx)
    22  	if len(md[remoteAddrKey]) != 0 {
    23  		remoteAddr = md[remoteAddrKey][0]
    24  	}
    25  	if len(md[certCNKey]) != 0 {
    26  		cn = md[certCNKey][0]
    27  	}
    28  	if len(md[certOrgKey]) != 0 {
    29  		org = md[certOrgKey][0]
    30  	}
    31  	ous = md[certOUKey]
    32  	return
    33  }
    34  
    35  func isForwardedRequest(ctx context.Context) bool {
    36  	md, _ := metadata.FromIncomingContext(ctx)
    37  	if len(md[certForwardedKey]) != 1 {
    38  		return false
    39  	}
    40  	return md[certForwardedKey][0] == "true"
    41  }
    42  
    43  // WithMetadataForwardTLSInfo reads certificate from context and returns context where
    44  // ForwardCert is set based on original certificate.
    45  func WithMetadataForwardTLSInfo(ctx context.Context) (context.Context, error) {
    46  	md, ok := metadata.FromIncomingContext(ctx)
    47  	if !ok {
    48  		md = metadata.MD{}
    49  	}
    50  
    51  	ous := []string{}
    52  	org := ""
    53  	cn := ""
    54  
    55  	certSubj, err := certSubjectFromContext(ctx)
    56  	if err == nil {
    57  		cn = certSubj.CommonName
    58  		ous = certSubj.OrganizationalUnit
    59  		if len(certSubj.Organization) > 0 {
    60  			org = certSubj.Organization[0]
    61  		}
    62  	}
    63  
    64  	// If there's no TLS cert, forward with blank TLS metadata.
    65  	// Note that the presence of this blank metadata is extremely
    66  	// important. Without it, it would look like manager is making
    67  	// the request directly.
    68  	md[certForwardedKey] = []string{"true"}
    69  	md[certCNKey] = []string{cn}
    70  	md[certOrgKey] = []string{org}
    71  	md[certOUKey] = ous
    72  	peer, ok := peer.FromContext(ctx)
    73  	if ok {
    74  		md[remoteAddrKey] = []string{peer.Addr.String()}
    75  	}
    76  
    77  	return metadata.NewOutgoingContext(ctx, md), nil
    78  }