Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion demo/drkey/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func realMain() int {
DstHost: clientAddr.Host.IP.String(),
}

daemon, err := daemon.NewService(scionEnv.Daemon()).Connect(ctx)
daemon, err := daemon.NewAutoConnector(ctx, daemon.WithDaemon(scionEnv.Daemon()))
if err != nil {
fmt.Fprintln(os.Stderr, "Error dialing SCION Daemon:", err)
return 1
Expand Down
7 changes: 6 additions & 1 deletion doc/command/scion-pki/scion-pki_certificate_renew.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ Options
The CAs are tried in order until success or all of them failed.
--ca is mutually exclusive with --remote
--common-name string The common name that replaces the common name in the subject template
--config-dir string Directory containing topology.json and certs/ for standalone mode.
If both --sciond and --config-dir are set, --sciond takes priority.
Defaults to /etc/scion on Linux.
--curve string The elliptic curve to use (P-256|P-384|P-521) (default "P-256")
--expires-in string Remaining time threshold for renewal
--features strings enable development features ()
Expand All @@ -140,7 +143,9 @@ Options
and all specified remotes are tried in order until success or all of them failed.
--remote is mutually exclusive with --ca.
--reuse-key Reuse the provided private key instead of creating a fresh private key
--sciond string SCION Daemon address. (default "127.0.0.1:30255")
--sciond string Connect to SCION Daemon at the specified address instead of using
the local topology.json (IP:Port or "default" for 127.0.0.1:30255).
If both --sciond and --config-dir are set, --sciond takes priority.
--sequence string Space separated list of hop predicates
--subject string The path to the custom subject for the CSR
--timeout duration The timeout for the renewal request per CA (default 10s)
Expand Down
15 changes: 10 additions & 5 deletions doc/command/scion/scion_address.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,16 @@ Options

::

-h, --help help for address
--isd-as isd-as The local ISD-AS to use. (default 0-0)
--json Write the output as machine readable json
-l, --local ip Local IP address to listen on. (default invalid IP)
--sciond string SCION Daemon address. (default "127.0.0.1:30255")
--config-dir string Directory containing topology.json and certs/ for standalone mode.
If both --sciond and --config-dir are set, --sciond takes priority.
Defaults to /etc/scion on Linux.
-h, --help help for address
--isd-as isd-as The local ISD-AS to use. (default 0-0)
--json Write the output as machine readable json
-l, --local ip Local IP address to listen on. (default invalid IP)
--sciond string Connect to SCION Daemon at the specified address instead of using
the local topology.json (IP:Port or "default" for 127.0.0.1:30255).
If both --sciond and --config-dir are set, --sciond takes priority.

SEE ALSO
~~~~~~~~
Expand Down
7 changes: 6 additions & 1 deletion doc/command/scion/scion_ping.rst
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ Options

::

--config-dir string Directory containing topology.json and certs/ for standalone mode.
If both --sciond and --config-dir are set, --sciond takes priority.
Defaults to /etc/scion on Linux.
-c, --count uint16 total number of packets to send
--epic Enable EPIC for path probing.
--format string Specify the output format (human|json|yaml) (default "human")
Expand All @@ -107,7 +110,9 @@ Options
the total size of the packet is still variable size due to the variable size of
the SCION path.
--refresh set refresh flag for path request
--sciond string SCION Daemon address. (default "127.0.0.1:30255")
--sciond string Connect to SCION Daemon at the specified address instead of using
the local topology.json (IP:Port or "default" for 127.0.0.1:30255).
If both --sciond and --config-dir are set, --sciond takes priority.
--sequence string Space separated list of hop predicates
--timeout duration timeout per packet (default 1s)
--tracing.agent string Tracing agent address
Expand Down
7 changes: 6 additions & 1 deletion doc/command/scion/scion_showpaths.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ Options

::

--config-dir string Directory containing topology.json and certs/ for standalone mode.
If both --sciond and --config-dir are set, --sciond takes priority.
Defaults to /etc/scion on Linux.
--epic Enable EPIC.
-e, --extended Show extended path meta data information
--format string Specify the output format (human|json|yaml) (default "human")
Expand All @@ -101,7 +104,9 @@ Options
--no-color disable colored output
--no-probe Do not probe the paths and print the health status
-r, --refresh Set refresh flag for SCION Daemon path request
--sciond string SCION Daemon address. (default "127.0.0.1:30255")
--sciond string Connect to SCION Daemon at the specified address instead of using
the local topology.json (IP:Port or "default" for 127.0.0.1:30255).
If both --sciond and --config-dir are set, --sciond takes priority.
--sequence string Space separated list of hop predicates
--timeout duration Timeout (default 5s)
--tracing.agent string Tracing agent address
Expand Down
7 changes: 6 additions & 1 deletion doc/command/scion/scion_traceroute.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ Options

::

--config-dir string Directory containing topology.json and certs/ for standalone mode.
If both --sciond and --config-dir are set, --sciond takes priority.
Defaults to /etc/scion on Linux.
--epic Enable EPIC.
--format string Specify the output format (human|json|yaml) (default "human")
-h, --help help for traceroute
Expand All @@ -88,7 +91,9 @@ Options
--log.level string Console logging level verbosity (debug|info|error)
--no-color disable colored output
--refresh set refresh flag for path request
--sciond string SCION Daemon address. (default "127.0.0.1:30255")
--sciond string Connect to SCION Daemon at the specified address instead of using
the local topology.json (IP:Port or "default" for 127.0.0.1:30255).
If both --sciond and --config-dir are set, --sciond takes priority.
--sequence string Space separated list of hop predicates
--timeout duration timeout per packet (default 1s)
--tracing.agent string Tracing agent address
Expand Down
1 change: 0 additions & 1 deletion private/app/flag/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/addr:go_default_library",
"//pkg/daemon:go_default_library",
"//private/app/env:go_default_library",
"@com_github_spf13_pflag//:go_default_library",
"@com_github_stretchr_testify//assert:go_default_library",
Expand Down
115 changes: 96 additions & 19 deletions private/app/flag/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"io/fs"
"net/netip"
"os"
"runtime"
"sync"

"github.com/spf13/pflag"
Expand All @@ -34,6 +35,8 @@ const (
defaultDaemon = daemon.DefaultAPIAddress

defaultEnvironmentFile = "/etc/scion/environment.json"

defaultConfigDirLinux = "/etc/scion"
)

type stringVal string
Expand Down Expand Up @@ -77,15 +80,17 @@ func (v *ipVal) String() string { return netip.Addr(*v).String() }
// SCIONEnvironment can be used to access the common SCION configuration values,
// like the SCION daemon address and the local IP as well as the local ISD-AS.
type SCIONEnvironment struct {
sciondFlag *pflag.Flag
sciondEnv *string
ia addr.IA
iaFlag *pflag.Flag
local netip.Addr
localEnv *netip.Addr
localFlag *pflag.Flag
file env.SCION
filepath string
sciondFlag *pflag.Flag
sciondEnv *string
ia addr.IA
iaFlag *pflag.Flag
local netip.Addr
localEnv *netip.Addr
localFlag *pflag.Flag
configDir string
configDirFlag *pflag.Flag
file env.SCION
filepath string

mtx sync.Mutex
}
Expand All @@ -98,13 +103,59 @@ func (e *SCIONEnvironment) Register(flagSet *pflag.FlagSet) {
e.mtx.Lock()
defer e.mtx.Unlock()

sciond := defaultDaemon
e.sciondFlag = flagSet.VarPF((*stringVal)(&sciond), "sciond", "",
"SCION Daemon address.")
e.iaFlag = flagSet.VarPF((*iaVal)(&e.ia), "isd-as", "",
"The local ISD-AS to use.")
e.localFlag = flagSet.VarPF((*ipVal)(&e.local), "local", "l",
"Local IP address to listen on.")
sciond := ""
e.sciondFlag = flagSet.VarPF(
(*stringVal)(&sciond), "sciond", "",
`Connect to SCION Daemon at the specified address instead of using
the local topology.json (IP:Port or "default" for `+defaultDaemon+`).
If both --sciond and --config-dir are set, --sciond takes priority.`,
)

configDirHelp := `Directory containing topology.json and certs/ for standalone mode.
If both --sciond and --config-dir are set, --sciond takes priority.
`
if runtime.GOOS == "linux" {
configDirHelp += `Defaults to ` + defaultConfigDirLinux + ` on Linux.`
} else {
configDirHelp += `Required on this platform (no default).`
}
e.configDirFlag = flagSet.VarPF(
(*stringVal)(&e.configDir), "config-dir", "",
configDirHelp,
)
}

// Validate checks that the flags are consistent.
// Returns an error if neither --sciond nor --config-dir is set and there's no default
// (i.e., on non-Linux platforms where --config-dir has no default).
func (e *SCIONEnvironment) Validate() error {
e.mtx.Lock()
defer e.mtx.Unlock()

sciondSet := e.sciondFlag != nil && e.sciondFlag.Changed
configDirSet := e.configDirFlag != nil && e.configDirFlag.Changed

// If either flag is explicitly set, we're good
if sciondSet || configDirSet {
return nil
}

// Check if there's a daemon configured via environment
if e.sciondEnv != nil {
return nil
}

// On Linux, we have a default config directory
if runtime.GOOS == "linux" {
return nil
}

// On non-Linux platforms with no flags set, we need either --sciond or --config-dir
return serrors.New("either --sciond or --config-dir must be specified on this platform")
}

// LoadExternalVar loads variables from the SCION environment file and from the
Expand Down Expand Up @@ -163,18 +214,25 @@ func (e *SCIONEnvironment) loadEnv() error {
return nil
}

// Daemon returns the path to the SCION daemon. The value is loaded from one of
// the following sources with the precedence as listed:
// 1. Command line flag
// 2. Environment variable
// Daemon returns the SCION daemon address if explicitly configured.
// Returns empty string if no daemon was configured, allowing the caller
// to fall back to using the local topology.
// The value is loaded from one of the following sources with precedence:
// 1. Command line flag (--sciond)
// 2. Environment variable (SCION_DAEMON)
// 3. Environment configuration file
// 4. Default value.
//
// If none are set, returns empty string (not the default address).
func (e *SCIONEnvironment) Daemon() string {
e.mtx.Lock()
defer e.mtx.Unlock()

if e.sciondFlag != nil && e.sciondFlag.Changed {
return e.sciondFlag.Value.String()
value := e.sciondFlag.Value.String()
if value == "default" {
return defaultDaemon
}
return value
}
if e.sciondEnv != nil {
return *e.sciondEnv
Expand All @@ -186,7 +244,7 @@ func (e *SCIONEnvironment) Daemon() string {
if as, ok := e.file.ASes[ia]; ok && as.DaemonAddress != "" {
return as.DaemonAddress
}
return defaultDaemon
return ""
}

// Local returns the loca IP to listen on. The value is loaded from one of the
Expand All @@ -206,3 +264,22 @@ func (e *SCIONEnvironment) Local() netip.Addr {
}
return netip.Addr{}
}

// ConfigDir returns the configuration directory for standalone mode.
// The value is determined with the following precedence:
// 1. Command line flag (--config-dir)
// 2. On Linux: defaults to /etc/scion
// 3. On other platforms: returns empty string (must be specified via flag)
func (e *SCIONEnvironment) ConfigDir() string {
e.mtx.Lock()
defer e.mtx.Unlock()

if e.configDirFlag != nil && e.configDirFlag.Changed {
return e.configDir
}
// Default to /etc/scion on Linux only
if runtime.GOOS == "linux" {
return defaultConfigDirLinux
}
return ""
}
68 changes: 66 additions & 2 deletions private/app/flag/env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ import (
"encoding/json"
"net/netip"
"os"
"runtime"
"testing"

"github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/scionproto/scion/pkg/addr"
"github.com/scionproto/scion/pkg/daemon"
"github.com/scionproto/scion/private/app/env"
"github.com/scionproto/scion/private/app/flag"
)
Expand Down Expand Up @@ -80,7 +80,7 @@ func TestSCIONEnvironment(t *testing.T) {
flags: noFlags,
env: noEnv,
file: noFile,
daemon: daemon.DefaultAPIAddress,
daemon: "",
local: netip.Addr{},
},
"flag values set": {
Expand Down Expand Up @@ -140,3 +140,67 @@ func tempEnv(t *testing.T, key, val string) {
require.NoError(t, os.Setenv(key, val))
t.Cleanup(func() { require.NoError(t, os.Unsetenv(key)) })
}

func TestSCIONEnvironmentConfigDir(t *testing.T) {
defaultDir := ""
if runtime.GOOS == "linux" {
defaultDir = "/etc/scion"
}

testCases := map[string]struct {
flags []string
configDir string
}{
"no flag": {
flags: []string{},
configDir: defaultDir,
},
"config-dir flag set": {
flags: []string{"--config-dir", "/custom/path"},
configDir: "/custom/path",
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
var env flag.SCIONEnvironment
fs := pflag.NewFlagSet("testSet", pflag.ContinueOnError)
env.Register(fs)
require.NoError(t, fs.Parse(tc.flags))
assert.Equal(t, tc.configDir, env.ConfigDir())
})
}
}

func TestSCIONEnvironmentValidate(t *testing.T) {
testCases := map[string]struct {
flags []string
wantErr bool
}{
"sciond set": {
flags: []string{"--sciond", "127.0.0.1:30255"},
wantErr: false,
},
"config-dir set": {
flags: []string{"--config-dir", "/custom/path"},
wantErr: false,
},
"both flags set - sciond takes priority": {
flags: []string{"--sciond", "127.0.0.1:30255", "--config-dir", "/custom/path"},
wantErr: false,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
var env flag.SCIONEnvironment
fs := pflag.NewFlagSet("testSet", pflag.ContinueOnError)
env.Register(fs)
require.NoError(t, fs.Parse(tc.flags))
err := env.Validate()
if tc.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
2 changes: 1 addition & 1 deletion scion-pki/certs/renew.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ The template is expressed in JSON. A valid example::
// Setup basic state.
daemonCtx, daemonCancel := context.WithTimeout(ctx, time.Second)
defer daemonCancel()
sd, err := daemon.NewService(daemonAddr).Connect(daemonCtx)
sd, err := daemon.NewAutoConnector(ctx, daemon.WithDaemon(daemonAddr))
if err != nil {
return serrors.Wrap("connecting to SCION Daemon", err)
}
Expand Down
Loading
Loading