Skip to content
This repository has been archived by the owner on Jul 28, 2024. It is now read-only.

Commit

Permalink
Adds properties package (#399)
Browse files Browse the repository at this point in the history
Signed-off-by: Takeshi Yoneda <[email protected]>
  • Loading branch information
mathetake authored Oct 3, 2023
1 parent d9fa874 commit 91314e8
Show file tree
Hide file tree
Showing 6 changed files with 573 additions and 2 deletions.
165 changes: 165 additions & 0 deletions properties/connection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package properties

import "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"

// This file hosts helper functions to retrieve connection-related properties as described in:
// https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes#connection-attributes

var (
sourceAddress = []string{"source", "address"}
sourcePort = []string{"source", "port"}
destinationAddress = []string{"destination", "address"}
destinationPort = []string{"destination", "port"}
connectionID = []string{"connection", "id"}
connectionMtls = []string{"connection", "mtls"}
connectionRequestedServerName = []string{"connection", "requested_server_name"}
connectionTlsVersion = []string{"connection", "tls_version"}
connectionSubjectLocalCert = []string{"connection", "subject_local_certificate"}
connectionSubjectPeerCert = []string{"connection", "subject_peer_certificate"}
connectionDnsSanLocalCert = []string{"connection", "dns_san_local_certificate"}
connectionDnsSanPeerCert = []string{"connection", "dns_san_peer_certificate"}
connectionUriSanLocalCert = []string{"connection", "uri_san_local_certificate"}
connectionUriSanPeerCert = []string{"connection", "uri_san_peer_certificate"}
connectionSha256PeerCertDigest = []string{"connection", "sha256_peer_certificate_digest"}
connectionTerminationDetails = []string{"connection", "termination_details"}
)

// GetDownstreamRemoteAddress returns the remote address of the downstream connection.
func GetDownstreamRemoteAddress() (string, error) {
downstreamRemoteAddress, err := getPropertyString(sourceAddress)
if err != nil {
return "", err
}
return downstreamRemoteAddress, nil
}

// GetDownstreamRemotePort returns the remote port of the downstream connection.
func GetDownstreamRemotePort() (uint64, error) {
downstreamRemotePort, err := getPropertyUint64(sourcePort)
if err != nil {
return 0, err
}
return downstreamRemotePort, nil
}

// GetDownstreamLocalAddress returns the local address of the downstream connection.
func GetDownstreamLocalAddress() (string, error) {
downstreamLocalAddress, err := getPropertyString(destinationAddress)
if err != nil {
return "", err
}
return downstreamLocalAddress, nil
}

// GetDownstreamLocalPort returns the local port of the downstream connection.
func GetDownstreamLocalPort() (uint64, error) {
downstreamLocalPort, err := getPropertyUint64(destinationPort)
if err != nil {
return 0, err
}
return downstreamLocalPort, nil
}

// GetDownstreamConnectionID returns the connection ID of the downstream connection.
func GetDownstreamConnectionID() (uint64, error) {
downstreamConnectionId, err := getPropertyUint64(connectionID)
if err != nil {
return 0, err
}
return downstreamConnectionId, nil
}

// IsDownstreamConnectionTls returns true if the downstream connection is TLS.
func IsDownstreamConnectionTls() (bool, error) {
downstreamConnectionTls, err := getPropertyBool(connectionMtls)
if err != nil {
return false, err
}
return downstreamConnectionTls, nil
}

// GetDownstreamRequestedServerName returns the requested server name of the downstream connection.
func GetDownstreamRequestedServerName() (string, error) {
downstreamRequestedServerName, err := getPropertyString(connectionRequestedServerName)
if err != nil {
return "", err
}
return downstreamRequestedServerName, nil
}

// GetDownstreamTlsVersion returns the TLS version of the downstream connection.
func GetDownstreamTlsVersion() (string, error) {
downstreamTlsVersion, err := getPropertyString(connectionTlsVersion)
if err != nil {
return "", err
}
return downstreamTlsVersion, nil
}

// GetDownstreamSubjectLocalCertificate returns the subject field of the local certificate in the downstream TLS connection.
func GetDownstreamSubjectLocalCertificate() (string, error) {
downstreamSubjectLocalCertificate, err := getPropertyString(connectionSubjectLocalCert)
if err != nil {
return "", err
}
return downstreamSubjectLocalCertificate, nil
}

// GetDownstreamSubjectPeerCertificate returns the subject field of the peer certificate in the downstream TLS connection.
func GetDownstreamSubjectPeerCertificate() (string, error) {
downstreamSubjectPeerCertificate, err := getPropertyString(connectionSubjectPeerCert)
if err != nil {
return "", err
}
return downstreamSubjectPeerCertificate, nil
}

// GetDownstreamDnsSanLocalCertificate returns The first DNS entry in the SAN field of the local certificate in the downstream TLS connection.
func GetDownstreamDnsSanLocalCertificate() (string, error) {
downstreamDnsSanLocalCertificate, err := getPropertyString(connectionDnsSanLocalCert)
if err != nil {
return "", err
}
return downstreamDnsSanLocalCertificate, nil
}

// GetDownstreamDnsSanPeerCertificate returns The first DNS entry in the SAN field of the peer certificate in the downstream TLS connection.
func GetDownstreamDnsSanPeerCertificate() (string, error) {
downstreamDnsSanPeerCertificate, err := getPropertyString(connectionDnsSanPeerCert)
if err != nil {
return "", err
}
return downstreamDnsSanPeerCertificate, nil
}

// GetDownstreamUriSanLocalCertificate returns the first URI entry in the SAN field of the local certificate in the downstream TLS connection
func GetDownstreamUriSanLocalCertificate() (string, error) {
downstreamUriSanLocalCertificate, err := getPropertyString(connectionUriSanLocalCert)
if err != nil {
return "", err
}
return downstreamUriSanLocalCertificate, nil
}

// GetDownstreamUriSanPeerCertificate returns The first URI entry in the SAN field of the peer certificate in the downstream TLS connection.
func GetDownstreamUriSanPeerCertificate() (string, error) {
downstreamUriSanPeerCertificate, err := getPropertyString(connectionUriSanPeerCert)
if err != nil {
return "", err
}
return downstreamUriSanPeerCertificate, nil
}

// GetDownstreamSha256PeerCertificateDigest returns the SHA256 digest of a peer certificate digest of the downstream connection.
func GetDownstreamSha256PeerCertificateDigest() ([]byte, error) {
return proxywasm.GetProperty(connectionSha256PeerCertDigest)
}

// GetDownstreamTerminationDetails returns the internal termination details of the connection (subject to change).
func GetDownstreamTerminationDetails() (string, error) {
downstreamTerminationDetails, err := getPropertyString(connectionTerminationDetails)
if err != nil {
return "", err
}
return downstreamTerminationDetails, nil
}
180 changes: 180 additions & 0 deletions properties/connection_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package properties

import (
"encoding/binary"
"testing"

"github.com/stretchr/testify/require"

"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/proxytest"
)

func TestGetDownstreamRemoteAddress(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(sourceAddress, []byte("1.2.3.4"))
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamRemoteAddress()
require.NoError(t, err)
require.Equal(t, "1.2.3.4", result)
}

func TestGetDownstreamRemotePort(t *testing.T) {
var u64 [8]byte
binary.LittleEndian.PutUint64(u64[:], 1234)
opt := proxytest.NewEmulatorOption().WithProperty(sourcePort, u64[:])
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamRemotePort()
require.NoError(t, err)
require.Equal(t, uint64(1234), result)
}

func TestGetDownstreamLocalAddress(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(destinationAddress, []byte("1.2.3.4"))
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamLocalAddress()
require.NoError(t, err)
require.Equal(t, "1.2.3.4", result)
}

func TestGetDownstreamLocalPort(t *testing.T) {
var u64 [8]byte
binary.LittleEndian.PutUint64(u64[:], 1234)
opt := proxytest.NewEmulatorOption().WithProperty(destinationPort, u64[:])
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamLocalPort()
require.NoError(t, err)
require.Equal(t, uint64(1234), result)
}

func TestGetDownstreamConnectionID(t *testing.T) {
var u64 [8]byte
binary.LittleEndian.PutUint64(u64[:], 1234)
opt := proxytest.NewEmulatorOption().WithProperty(connectionID, u64[:])
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamConnectionID()
require.NoError(t, err)
require.Equal(t, uint64(1234), result)
}

func TestIsDownstreamConnectionTls(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(connectionMtls, []byte{1})
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := IsDownstreamConnectionTls()
require.NoError(t, err)
require.Equal(t, true, result)
}

func TestGetDownstreamRequestedServerName(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(connectionRequestedServerName, []byte("example.com"))
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamRequestedServerName()
require.NoError(t, err)
require.Equal(t, "example.com", result)
}

func TestGetDownstreamTlsVersion(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(connectionTlsVersion, []byte("TLSv1.3"))
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamTlsVersion()
require.NoError(t, err)
require.Equal(t, "TLSv1.3", result)
}

func TestGetDownstreamSubjectLocalCertificate(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(connectionSubjectLocalCert,
[]byte("CN=example.com,OU=IT,O=example,L=San Francisco,ST=California,C=US"))
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamSubjectLocalCertificate()
require.NoError(t, err)
require.Equal(t, "CN=example.com,OU=IT,O=example,L=San Francisco,ST=California,C=US", result)
}

func TestGetDownstreamSubjectPeerCertificate(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(connectionSubjectPeerCert,
[]byte("CN=example.com,OU=IT,O=example,L=San Francisco,ST=California,C=US"))
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamSubjectPeerCertificate()
require.NoError(t, err)
require.Equal(t, "CN=example.com,OU=IT,O=example,L=San Francisco,ST=California,C=US", result)
}

func TestGetDownstreamDnsSanLocalCertificate(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(connectionDnsSanLocalCert, []byte("example.com"))
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamDnsSanLocalCertificate()
require.NoError(t, err)
require.Equal(t, "example.com", result)
}

func TestGetDownstreamDnsSanPeerCertificate(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(connectionDnsSanPeerCert, []byte("example.com"))
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamDnsSanPeerCertificate()
require.NoError(t, err)
require.Equal(t, "example.com", result)
}

func TestGetDownstreamUriSanLocalCertificate(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(connectionUriSanLocalCert, []byte("example.com"))
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamUriSanLocalCertificate()
require.NoError(t, err)
require.Equal(t, "example.com", result)
}

func TestGetDownstreamUriSanPeerCertificate(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(connectionUriSanPeerCert, []byte("example.com"))
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamUriSanPeerCertificate()
require.NoError(t, err)
require.Equal(t, "example.com", result)
}

func TestGetDownstreamSha256PeerCertificateDigest(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(connectionSha256PeerCertDigest,
[]byte{0x01, 0x02, 0x03, 0x04})
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamSha256PeerCertificateDigest()
require.NoError(t, err)
require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, result)
}

func TestGetDownstreamTerminationDetails(t *testing.T) {
opt := proxytest.NewEmulatorOption().WithProperty(connectionTerminationDetails,
[]byte("connection closed"))
_, reset := proxytest.NewHostEmulator(opt)
defer reset()

result, err := GetDownstreamTerminationDetails()
require.NoError(t, err)
require.Equal(t, "connection closed", result)
}
6 changes: 6 additions & 0 deletions properties/properties.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Package properties provides helper functions for retrieving properties in the Envoy/Istio specific environment.
//
// WARNING: There's absolutely no guarantee that all properties will be available across versions, and the availability is totally
// dependent of the configuration, so users are highly encouraged to ensure that plugins work as expected when deploying
// the plugins using these properties.
package properties
Loading

0 comments on commit 91314e8

Please sign in to comment.