Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding enclave restricted flags #1668

Merged
merged 15 commits into from
Dec 5, 2023
Merged
26 changes: 20 additions & 6 deletions dockerfiles/enclave.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
# deploy = copies over only the enclave executable without the source
# in a lightweight base image specialized for deployment and prepares the /data/ folder.

# Final container folder structure:
# /home/obscuro/data contains working files for the enclave
# /home/obscuro/go-obscuro/go/enclave/main contains the executable for the enclave
#

# Defaults to restricted flag mode
ARG TESTMODE=false
otherview marked this conversation as resolved.
Show resolved Hide resolved

FROM ghcr.io/edgelesssys/ego-dev:v1.3.0 AS build-base

# setup container data structure
Expand All @@ -26,19 +34,25 @@ WORKDIR /home/obscuro/go-obscuro/go/enclave/main
RUN --mount=type=cache,target=/root/.cache/go-build \
ego-go build

# New build stage for compiling the enclave with restricted flags mode
FROM build-enclave as build-enclave-testmode-false
# Sign the enclave executable
RUN ego sign main
RUN ego sign enclave.json

# New build stage for compiling the enclave without restricted flags mode
FROM build-enclave as build-enclave-testmode-true
# Sign the enclave executable
RUN ego sign enclave-test.json

# Tag the restricted mode as the current build
FROM build-enclave-testmode-${TESTMODE} as build-enclave

# Final container folder structure:
# /home/obscuro/data contains working files for the enclave
# /home/obscuro/go-obscuro/go/enclave/main contains the executable for the enclave
#
# Trigger a new build stage and use the smaller ego version:
FROM ghcr.io/edgelesssys/ego-deploy:v1.3.0
otherview marked this conversation as resolved.
Show resolved Hide resolved

# Copy just the binary for the enclave into this build stage
COPY --from=build-enclave \
/home/obscuro/go-obscuro/go/enclave/main home/obscuro/go-obscuro/go/enclave/main
/home/obscuro/go-obscuro/go/enclave/main /home/obscuro/go-obscuro/go/enclave/main
otherview marked this conversation as resolved.
Show resolved Hide resolved

WORKDIR /home/obscuro/go-obscuro/go/enclave/main

Expand Down
299 changes: 0 additions & 299 deletions go.sum

Large diffs are not rendered by default.

133 changes: 133 additions & 0 deletions go/common/flag/flag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package flag

import (
"flag"
"fmt"
)

type TenFlag struct {
Name string
Value any
FlagType string
Description string
DefaultValue any
}

func NewStringFlag(name, defaultValue, description string) *TenFlag {
return &TenFlag{
Name: name,
Value: "",
FlagType: "string",
Description: description,
DefaultValue: defaultValue,
}
}

func NewIntFlag(name string, defaultValue int, description string) *TenFlag {
return &TenFlag{
Name: name,
Value: 0,
FlagType: "int",
Description: description,
DefaultValue: defaultValue,
}
}

func NewBoolFlag(name string, defaultValue bool, description string) *TenFlag {
return &TenFlag{
Name: name,
Value: false,
FlagType: "bool",
Description: description,
DefaultValue: defaultValue,
}
}

func NewInt64Flag(name string, defaultValue int64, description string) *TenFlag {
return &TenFlag{
Name: name,
Value: false,
otherview marked this conversation as resolved.
Show resolved Hide resolved
FlagType: "int64",
Description: description,
DefaultValue: defaultValue,
}
}

func NewUint64Flag(name string, defaultValue uint64, description string) *TenFlag {
return &TenFlag{
Name: name,
Value: false,
otherview marked this conversation as resolved.
Show resolved Hide resolved
FlagType: "uint64",
Description: description,
DefaultValue: defaultValue,
}
}

func (f TenFlag) String() string {
if ptrVal, ok := f.Value.(*string); ok {
return *ptrVal
}
return f.Value.(string)
}

func (f TenFlag) Int() int {
if ptrVal, ok := f.Value.(*int); ok {
return *ptrVal
}
return f.Value.(int)
}

func (f TenFlag) Int64() int64 {
if ptrVal, ok := f.Value.(*int64); ok {
return *ptrVal
}
return f.Value.(int64)
}

func (f TenFlag) Uint64() uint64 {
if ptrVal, ok := f.Value.(*uint64); ok {
return *ptrVal
}
return f.Value.(uint64)
}

func (f TenFlag) Bool() bool {
if ptrVal, ok := f.Value.(*bool); ok {
return *ptrVal
}
return f.Value.(bool)
}

func (f TenFlag) IsSet() bool {
found := false
flag.Visit(func(fl *flag.Flag) {
if fl.Name == f.Name {
found = true
}
})
return found
}

func CreateCLIFlags(flags map[string]*TenFlag) error {
for _, tflag := range flags {
switch tflag.FlagType {
case "string":
tflag.Value = flag.String(tflag.Name, tflag.DefaultValue.(string), tflag.Description)
case "bool":
tflag.Value = flag.Bool(tflag.Name, tflag.DefaultValue.(bool), tflag.Description)
case "int":
tflag.Value = flag.Int(tflag.Name, tflag.DefaultValue.(int), tflag.Description)
case "int64":
tflag.Value = flag.Int64(tflag.Name, tflag.DefaultValue.(int64), tflag.Description)
case "uint64":
tflag.Value = flag.Uint64(tflag.Name, tflag.DefaultValue.(uint64), tflag.Description)
default:
return fmt.Errorf("unexpected flag type %s", tflag.FlagType)
}
}
return nil
}

func Parse() {
flag.Parse()
}
73 changes: 73 additions & 0 deletions go/config/enclave_cli_flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package config

import "github.com/ten-protocol/go-ten/go/common/flag"

// Flag names.
const (
otherview marked this conversation as resolved.
Show resolved Hide resolved
HostIDFlag = "hostID"
HostAddressFlag = "hostAddress"
AddressFlag = "address"
NodeTypeFlag = "nodeType"
L1ChainIDFlag = "l1ChainID"
ObscuroChainIDFlag = "obscuroChainID"
WillAttestFlag = "willAttest"
ValidateL1BlocksFlag = "validateL1Blocks"
ManagementContractAddressFlag = "managementContractAddress"
LogLevelFlag = "logLevel"
LogPathFlag = "logPath"
UseInMemoryDBFlag = "useInMemoryDB"
EdgelessDBHostFlag = "edgelessDBHost"
SQLiteDBPathFlag = "sqliteDBPath"
ProfilerEnabledFlag = "profilerEnabled"
MinGasPriceFlag = "minGasPrice"
MessageBusAddressFlag = "messageBusAddress"
SequencerIDFlag = "sequencerID"
ObscuroGenesisFlag = "obscuroGenesis"
DebugNamespaceEnabledFlag = "debugNamespaceEnabled"
MaxBatchSizeFlag = "maxBatchSize"
MaxRollupSizeFlag = "maxRollupSize"
L2BaseFeeFlag = "l2BaseFee"
L2CoinbaseFlag = "l2Coinbase"
L2GasLimitFlag = "l2GasLimit"
)

// EnclaveFlags are the flags that the enclave can receive
func EnclaveFlags() map[string]*flag.TenFlag {
return map[string]*flag.TenFlag{
HostIDFlag: flag.NewStringFlag(HostIDFlag, "", "The 20 bytes of the address of the Obscuro host this enclave serves"),
HostAddressFlag: flag.NewStringFlag(HostAddressFlag, "", "The peer-to-peer IP address of the Obscuro host this enclave serves"),
AddressFlag: flag.NewStringFlag(AddressFlag, "", "The address on which to serve the Obscuro enclave service"),
NodeTypeFlag: flag.NewStringFlag(NodeTypeFlag, "", "The node's type (e.g. sequencer, validator)"),
WillAttestFlag: flag.NewBoolFlag(WillAttestFlag, false, "Whether the enclave will produce a verified attestation report"),
ValidateL1BlocksFlag: flag.NewBoolFlag(ValidateL1BlocksFlag, false, "Whether to validate incoming blocks using the hardcoded L1 genesis.json config"),
ManagementContractAddressFlag: flag.NewStringFlag(ManagementContractAddressFlag, "", "The management contract address on the L1"),
LogLevelFlag: flag.NewIntFlag(LogLevelFlag, 0, "The verbosity level of logs. (Defaults to Info)"),
LogPathFlag: flag.NewStringFlag(LogPathFlag, "", "The path to use for the enclave service's log file"),
EdgelessDBHostFlag: flag.NewStringFlag(EdgelessDBHostFlag, "", "Host address for the edgeless DB instance (can be empty if useInMemoryDB is true or if not using attestation"),
SQLiteDBPathFlag: flag.NewStringFlag(SQLiteDBPathFlag, "", "Filepath for the sqlite DB persistence file (can be empty if a throwaway file in /tmp/ is acceptable or if using InMemory DB or if using attestation/EdgelessDB)"),
MinGasPriceFlag: flag.NewInt64Flag(MinGasPriceFlag, 0, "The minimum gas price for mining a transaction"),
MessageBusAddressFlag: flag.NewStringFlag(MessageBusAddressFlag, "", "The address of the L1 message bus contract owned by the management contract."),
SequencerIDFlag: flag.NewStringFlag(SequencerIDFlag, "", "The 20 bytes of the address of the sequencer for this network"),
MaxBatchSizeFlag: flag.NewUint64Flag(MaxBatchSizeFlag, 0, "The maximum size a batch is allowed to reach uncompressed"),
MaxRollupSizeFlag: flag.NewUint64Flag(MaxRollupSizeFlag, 0, "The maximum size a rollup is allowed to reach"),
L2BaseFeeFlag: flag.NewUint64Flag(L2BaseFeeFlag, 0, ""),
L2CoinbaseFlag: flag.NewStringFlag(L2CoinbaseFlag, "", ""),
L2GasLimitFlag: flag.NewUint64Flag(L2GasLimitFlag, 0, ""),
ObscuroGenesisFlag: flag.NewStringFlag(ObscuroGenesisFlag, "", "The json string with the obscuro genesis"),
L1ChainIDFlag: flag.NewInt64Flag(L1ChainIDFlag, 0, "An integer representing the unique chain id of the Ethereum chain used as an L1 (default 1337)"),
ObscuroChainIDFlag: flag.NewInt64Flag(ObscuroChainIDFlag, 0, "An integer representing the unique chain id of the Obscuro chain (default 443)"),
UseInMemoryDBFlag: flag.NewBoolFlag(UseInMemoryDBFlag, false, "Whether the enclave will use an in-memory DB rather than persist data"),
ProfilerEnabledFlag: flag.NewBoolFlag(ProfilerEnabledFlag, false, "Runs a profiler instance (Defaults to false)"),
DebugNamespaceEnabledFlag: flag.NewBoolFlag(DebugNamespaceEnabledFlag, false, "Whether the debug namespace is enabled"),
}
}

// enclaveRestrictedFlags are the flags that the enclave can receive ONLY over the Ego signed enclave.json
var enclaveRestrictedFlags = []string{
L1ChainIDFlag,
ObscuroChainIDFlag,
ObscuroGenesisFlag,
UseInMemoryDBFlag,
ProfilerEnabledFlag,
DebugNamespaceEnabledFlag,
}
129 changes: 126 additions & 3 deletions go/config/enclave_config.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package config

import (
"fmt"
"math/big"
"os"
"strconv"
"strings"

"github.com/ten-protocol/go-ten/go/common"

gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/ten-protocol/go-ten/go/common"
"github.com/ten-protocol/go-ten/go/common/flag"
"github.com/ten-protocol/go-ten/go/common/log"

gethcommon "github.com/ethereum/go-ethereum/common"
gethlog "github.com/ethereum/go-ethereum/log"
)

Expand Down Expand Up @@ -100,3 +104,122 @@ func DefaultEnclaveConfig() *EnclaveConfig {
GasLimit: new(big.Int).SetUint64(params.MaxGasLimit / 6),
}
}

func NewConfigFromFlags(cliFlags map[string]*flag.TenFlag) (*EnclaveConfig, error) {
productionMode := true

// check if it's in production mode or not
val := os.Getenv("EDG_TESTMODE")
if val == "true" {
productionMode = false
fmt.Println("Using test mode flags")
} else {
fmt.Println("Using mandatory signed configurations.")
}

if productionMode {
envFlags, err := retrieveEnvFlags()
if err != nil {
return nil, fmt.Errorf("unable to retrieve env flags - %w", err)
}

// fail if any restricted flag is set via the cli
for _, envflag := range envFlags {
if cliflag, ok := cliFlags[envflag.Name]; ok && cliflag.IsSet() {
return nil, fmt.Errorf("restricted flag was set: %s", cliflag.Name)
}
}

// create the final flag usage
parsedFlags := map[string]*flag.TenFlag{}
for flagName, cliflag := range cliFlags {
parsedFlags[flagName] = cliflag
}
// env flags override CLI flags
for flagName, envflag := range envFlags {
parsedFlags[flagName] = envflag
}

return newConfig(parsedFlags)
}
return newConfig(cliFlags)
}

func retrieveEnvFlags() (map[string]*flag.TenFlag, error) {
parsedFlags := map[string]*flag.TenFlag{}

for _, eflag := range enclaveRestrictedFlags {
val := os.Getenv("EDG_" + strings.ToUpper(eflag))

// all env flags must be set
if val == "" {
return nil, fmt.Errorf("env var not set: %s", eflag)
}

switch EnclaveFlags()[eflag].FlagType {
case "string":
parsedFlag := flag.NewStringFlag(eflag, "", "")
parsedFlag.Value = val

parsedFlags[eflag] = parsedFlag
case "int64":
i, err := strconv.ParseInt(val, 10, 64)
if err != nil {
return nil, fmt.Errorf("unable to parse flag %s - %w", eflag, err)
}

parsedFlag := flag.NewIntFlag(eflag, 0, "")
parsedFlag.Value = i
parsedFlags[eflag] = parsedFlag
case "bool":
b, err := strconv.ParseBool(val)
if err != nil {
return nil, fmt.Errorf("unable to parse flag %s - %w", eflag, err)
}

parsedFlag := flag.NewBoolFlag(eflag, false, "")
parsedFlag.Value = b
parsedFlags[eflag] = parsedFlag
default:
return nil, fmt.Errorf("unexpected type: %s", EnclaveFlags()[eflag].FlagType)
}
}
return parsedFlags, nil
}

func newConfig(flags map[string]*flag.TenFlag) (*EnclaveConfig, error) {
cfg := DefaultEnclaveConfig()

nodeType, err := common.ToNodeType(flags[NodeTypeFlag].String())
if err != nil {
return nil, fmt.Errorf("unrecognised node type '%s'", flags[NodeTypeFlag].String())
}

cfg.HostID = gethcommon.HexToAddress(flags[HostIDFlag].String())
cfg.HostAddress = flags[HostAddressFlag].String()
cfg.Address = flags[AddressFlag].String()
cfg.NodeType = nodeType
cfg.L1ChainID = flags[L1ChainIDFlag].Int64()
cfg.ObscuroChainID = flags[ObscuroChainIDFlag].Int64()
cfg.WillAttest = flags[WillAttestFlag].Bool()
cfg.ValidateL1Blocks = flags[ValidateL1BlocksFlag].Bool()
cfg.ManagementContractAddress = gethcommon.HexToAddress(flags[ManagementContractAddressFlag].String())
cfg.LogLevel = flags[LogLevelFlag].Int()
cfg.LogPath = flags[LogPathFlag].String()
cfg.UseInMemoryDB = flags[UseInMemoryDBFlag].Bool()
cfg.EdgelessDBHost = flags[EdgelessDBHostFlag].String()
cfg.SqliteDBPath = flags[SQLiteDBPathFlag].String()
cfg.ProfilerEnabled = flags[ProfilerEnabledFlag].Bool()
cfg.MinGasPrice = big.NewInt(flags[MinGasPriceFlag].Int64())
cfg.MessageBusAddress = gethcommon.HexToAddress(flags[MessageBusAddressFlag].String())
cfg.SequencerID = gethcommon.HexToAddress(flags[SequencerIDFlag].String())
cfg.ObscuroGenesis = flags[ObscuroGenesisFlag].String()
cfg.DebugNamespaceEnabled = flags[DebugNamespaceEnabledFlag].Bool()
cfg.MaxBatchSize = flags[MaxBatchSizeFlag].Uint64()
cfg.MaxRollupSize = flags[MaxRollupSizeFlag].Uint64()
cfg.BaseFee = big.NewInt(0).SetUint64(flags[L2BaseFeeFlag].Uint64())
cfg.GasPaymentAddress = gethcommon.HexToAddress(flags[L2CoinbaseFlag].String())
cfg.GasLimit = big.NewInt(0).SetUint64(flags[L2GasLimitFlag].Uint64())
otherview marked this conversation as resolved.
Show resolved Hide resolved

return cfg, nil
}
Loading
Loading