Skip to content

Commit

Permalink
go/ekiden/cmd/ias: Use TLS for the IAS proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
Yawning committed Aug 28, 2019
1 parent 1dc8f8c commit 0c8088c
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 4 deletions.
8 changes: 8 additions & 0 deletions .buildkite/scripts/common_e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ EKIDEN_MRSIGNER=${EKIDEN_MRSIGNER:-"9affcfae47b848ec2caf1c49b4b283531e1cc425f935
# EKIDEN_COMMITTEE_DIR
# EKIDEN_GENESIS_FILE
# EKIDEN_IAS_PROXY_PORT
# EKIDEN_IAS_PROXY_CERT
# EKIDEN_EPOCHTIME_BACKEND
# EKIDEN_VALIDATOR_SOCKET
# EKIDEN_CLIENT_SOCKET
Expand Down Expand Up @@ -153,12 +154,15 @@ run_backend_tendermint_committee() {

# Run the IAS proxy if needed.
local ias_proxy_port=9001
local ias_dir=${committee_dir}/ias-proxy
rm -Rf {$ias_dir}

if [ "${EKIDEN_TEE_HARDWARE}" == "intel-sgx" ]; then
if [ "${EKIDEN_UNSAFE_SKIP_AVR_VERIFY}" == "" ]; then
# TODO: Ensure that IAS credentials are configured.
${EKIDEN_NODE} \
ias proxy \
--datadir ${ias_dir} \
--ias.debug.skip_auth \
--ias.auth.cert ${EKIDEN_IAS_CERT} \
--ias.auth.cert.ca ${EKIDEN_IAS_CERT} \
Expand All @@ -172,6 +176,7 @@ run_backend_tendermint_committee() {
# Mock, with a high-quality random SPID from random.org
${EKIDEN_NODE} \
ias proxy \
--datadir ${ias_dir} \
--ias.debug.mock \
--ias.use_genesis \
--genesis.file ${genesis_file} \
Expand All @@ -184,6 +189,7 @@ run_backend_tendermint_committee() {
fi

EKIDEN_IAS_PROXY_ENABLED=1
EKIDEN_IAS_PROXY_CERT=${ias_dir}/ias_proxy_cert.pem
fi

# Export some variables so compute workers can find them.
Expand Down Expand Up @@ -337,6 +343,7 @@ run_compute_node() {
--tendermint.consensus.timeout_commit 250ms \
--tendermint.debug.addr_book_lenient \
${EKIDEN_IAS_PROXY_ENABLED:+--ias.proxy_addr 127.0.0.1:${EKIDEN_IAS_PROXY_PORT}} \
${EKIDEN_IAS_PROXY_ENABLED:+--ias.tls ${EKIDEN_IAS_PROXY_CERT}} \
${EKIDEN_TEE_HARDWARE:+--ias.debug.skip_verify} \
--worker.compute.enabled \
--worker.compute.backend sandboxed \
Expand Down Expand Up @@ -577,6 +584,7 @@ run_keymanager_node() {
--tendermint.consensus.timeout_commit 250ms \
--tendermint.debug.addr_book_lenient \
${EKIDEN_IAS_PROXY_ENABLED:+--ias.proxy_addr 127.0.0.1:${EKIDEN_IAS_PROXY_PORT}} \
${EKIDEN_IAS_PROXY_ENABLED:+--ias.tls ${EKIDEN_IAS_PROXY_CERT}} \
${EKIDEN_TEE_HARDWARE:+--ias.debug.skip_verify} \
${EKIDEN_TEE_HARDWARE:+--worker.keymanager.tee_hardware ${EKIDEN_TEE_HARDWARE}} \
--worker.registration.entity ${EKIDEN_ENTITY_DESCRIPTOR} \
Expand Down
3 changes: 3 additions & 0 deletions go/common/sgx/ias/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ var (

// EvidenceSignatureContext is the signature context used for verifying evidence.
EvidenceSignatureContext = []byte("EkIASEvi")

// CommonName is the CommonName for the IAS proxy TLS certificate.
CommonName = "ias-proxy"
)

// GRPCAuthenticator is the interface used to authenticate gRPC requests.
Expand Down
5 changes: 3 additions & 2 deletions go/ekiden/cmd/common/grpc/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package grpc

import (
"crypto/tls"
"errors"
"path/filepath"

Expand All @@ -28,9 +29,9 @@ const (
//
// This internally takes a snapshot of the current global tracer, so
// make sure you initialize the global tracer before calling this.
func NewServerTCP() (*cmnGrpc.Server, error) {
func NewServerTCP(cert *tls.Certificate) (*cmnGrpc.Server, error) {
port := uint16(viper.GetInt(cfgGRPCPort))
return cmnGrpc.NewServerTCP("internal", port, nil, nil)
return cmnGrpc.NewServerTCP("internal", port, cert, nil)
}

// NewServerLocal constructs a new gRPC server service listening on
Expand Down
33 changes: 32 additions & 1 deletion go/ekiden/cmd/ias/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/spf13/cobra"
"github.com/spf13/viper"

tlsCert "github.com/oasislabs/ekiden/go/common/crypto/tls"
"github.com/oasislabs/ekiden/go/common/grpc"
"github.com/oasislabs/ekiden/go/common/logging"
"github.com/oasislabs/ekiden/go/common/sgx/ias"
Expand All @@ -33,6 +35,9 @@ const (
cfgDebugMock = "ias.debug.mock"
cfgDebugSkipAuth = "ias.debug.skip_auth"
cfgUseGenesis = "ias.use_genesis"

tlsKeyFilename = "ias_proxy.pem"
tlsCertFilename = "ias_proxy_cert.pem"
)

var (
Expand All @@ -58,6 +63,15 @@ type proxyEnv struct {
grpcSrv *grpc.Server
}

func tlsCertPaths(dataDir string) (string, string) {
var (
certPath = filepath.Join(dataDir, tlsCertFilename)
keyPath = filepath.Join(dataDir, tlsKeyFilename)
)

return certPath, keyPath
}

func doProxy(cmd *cobra.Command, args []string) {
var startOk bool
defer func() {
Expand All @@ -75,6 +89,23 @@ func doProxy(cmd *cobra.Command, args []string) {
cmdCommon.EarlyLogAndExit(err)
}

dataDir, err := cmdCommon.DataDirOrPwd()
if err != nil {
logger.Error("failed to query data directory",
"err", err,
)
return
}

tlsCertPath, tlsKeyPath := tlsCertPaths(dataDir)
cert, err := tlsCert.LoadOrGenerate(tlsCertPath, tlsKeyPath, ias.CommonName)
if err != nil {
logger.Error("failed to load or generate TLS cert",
"err", err,
)
return
}

endpoint, err := iasEndpointFromFlags()
if err != nil {
logger.Error("failed to initialize IAS endpoint",
Expand All @@ -84,7 +115,7 @@ func doProxy(cmd *cobra.Command, args []string) {
}

// Initialize the gRPC server.
env.grpcSrv, err = cmdGrpc.NewServerTCP()
env.grpcSrv, err = cmdGrpc.NewServerTCP(cert)
if err != nil {
logger.Error("failed to initialize gRPC server",
"err", err,
Expand Down
34 changes: 33 additions & 1 deletion go/ias/ias.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ package ias

import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"time"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"

"github.com/oasislabs/ekiden/go/common/cbor"
"github.com/oasislabs/ekiden/go/common/crypto/signature"
tlsCert "github.com/oasislabs/ekiden/go/common/crypto/tls"
"github.com/oasislabs/ekiden/go/common/identity"
"github.com/oasislabs/ekiden/go/common/logging"
"github.com/oasislabs/ekiden/go/common/sgx/ias"
Expand All @@ -19,6 +24,7 @@ import (

const (
cfgProxyAddress = "ias.proxy_addr"
cfgTLSCertFile = "ias.tls"
cfgDebugSkipVerify = "ias.debug.skip_verify"
)

Expand Down Expand Up @@ -141,7 +147,31 @@ func New(identity *identity.Identity) (*IAS, error) {
s.spidInfo = &ias.SPIDInfo{}
_ = s.spidInfo.SPID.UnmarshalBinary(make([]byte, ias.SPIDSize))
} else {
conn, err := grpc.Dial(proxyAddr, grpc.WithInsecure()) // TODO: TLS?
tlsCertFile := viper.GetString(cfgTLSCertFile)
if tlsCertFile == "" {
s.logger.Error("IAS proxy TLS certificate not configured")
return nil, errors.New("ias: proxy TLS certificate not configured")
}

proxyCert, err := tlsCert.LoadCertificate(tlsCertFile)
if err != nil {
return nil, err
}

parsedCert, err := x509.ParseCertificate(proxyCert.Certificate[0])
if err != nil {
return nil, err
}

certPool := x509.NewCertPool()
certPool.AddCert(parsedCert)
creds := credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{*identity.TLSCertificate},
RootCAs: certPool,
ServerName: ias.CommonName,
})

conn, err := grpc.Dial(proxyAddr, grpc.WithTransportCredentials(creds))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -177,11 +207,13 @@ func New(identity *identity.Identity) (*IAS, error) {
func RegisterFlags(cmd *cobra.Command) {
if !cmd.Flags().Parsed() {
cmd.Flags().String(cfgProxyAddress, "", "IAS proxy address")
cmd.Flags().String(cfgTLSCertFile, "", "IAS proxy TLS certificate")
cmd.Flags().Bool(cfgDebugSkipVerify, false, "skip IAS AVR signature verification (UNSAFE)")
}

for _, v := range []string{
cfgProxyAddress,
cfgTLSCertFile,
cfgDebugSkipVerify,
} {
_ = viper.BindPFlag(v, cmd.Flags().Lookup(v))
Expand Down

0 comments on commit 0c8088c

Please sign in to comment.