From 39fea054b0ea0dd7cd1c9c68837973be7bb3db9a Mon Sep 17 00:00:00 2001 From: roos Date: Fri, 8 Nov 2019 12:17:48 +0100 Subject: [PATCH] SPKI: Remove legacy config definitions Remove legacy config file definitions that are no longer used in v2 of the scion-pki tool. --- .../scion-pki/internal/v2/conf/BUILD.bazel | 9 - go/tools/scion-pki/internal/v2/conf/as.go | 344 ------------------ .../scion-pki/internal/v2/conf/as_test.go | 192 ---------- go/tools/scion-pki/internal/v2/conf/isd.go | 242 ------------ .../scion-pki/internal/v2/conf/isd_test.go | 172 --------- 5 files changed, 959 deletions(-) delete mode 100644 go/tools/scion-pki/internal/v2/conf/as.go delete mode 100644 go/tools/scion-pki/internal/v2/conf/as_test.go delete mode 100644 go/tools/scion-pki/internal/v2/conf/isd.go delete mode 100644 go/tools/scion-pki/internal/v2/conf/isd_test.go diff --git a/go/tools/scion-pki/internal/v2/conf/BUILD.bazel b/go/tools/scion-pki/internal/v2/conf/BUILD.bazel index 0bdd465a16..5b48606e8a 100644 --- a/go/tools/scion-pki/internal/v2/conf/BUILD.bazel +++ b/go/tools/scion-pki/internal/v2/conf/BUILD.bazel @@ -3,8 +3,6 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "as.go", - "isd.go", "key.go", "trc.go", "validity.go", @@ -13,7 +11,6 @@ go_library( visibility = ["//go/tools/scion-pki:__subpackages__"], deps = [ "//go/lib/addr:go_default_library", - "//go/lib/common:go_default_library", "//go/lib/scrypto:go_default_library", "//go/lib/scrypto/cert/v2:go_default_library", "//go/lib/scrypto/trc/v2:go_default_library", @@ -21,24 +18,18 @@ go_library( "//go/lib/util:go_default_library", "//go/tools/scion-pki/internal/pkicmn:go_default_library", "@com_github_burntsushi_toml//:go_default_library", - "@com_github_go_ini_ini//:go_default_library", ], ) go_test( name = "go_default_test", srcs = [ - "as_test.go", - "isd_test.go", "key_test.go", "trc_test.go", ], data = ["//go/tools/scion-pki/internal/v2/conf/testdata:data"], embed = [":go_default_library"], deps = [ - "//go/lib/addr:go_default_library", - "//go/lib/scrypto:go_default_library", - "//go/lib/xtest:go_default_library", "//go/tools/scion-pki/internal/v2/conf/testdata:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", diff --git a/go/tools/scion-pki/internal/v2/conf/as.go b/go/tools/scion-pki/internal/v2/conf/as.go deleted file mode 100644 index 63ab3eda8a..0000000000 --- a/go/tools/scion-pki/internal/v2/conf/as.go +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright 2018 ETH Zurich -// Copyright 2019 ETH Zurich, Anapaya Systems -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package conf - -import ( - "os" - "path/filepath" - "time" - - "github.com/go-ini/ini" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/common" - "github.com/scionproto/scion/go/lib/scrypto" - "github.com/scionproto/scion/go/lib/util" - "github.com/scionproto/scion/go/tools/scion-pki/internal/pkicmn" -) - -const ( - ErrASCertMissing common.ErrMsg = "AS Certificate section missing" - ErrInvalidValidityDuration common.ErrMsg = "invalid validity duration" - ErrIssuerMissing common.ErrMsg = "issuer not set in AS certificate" - ErrInvalidIssuer common.ErrMsg = "issuer is not valid" - ErrInvalidIssuerCertVersion common.ErrMsg = "issuer certificate version must not be zero" - ErrInvalidIssuerTRCVersion common.ErrMsg = "TRC version must not be zero" - ErrInvalidOptDistPoint common.ErrMsg = "invalid optional distribution point" - ErrValidityDurationNotSet common.ErrMsg = "validity duration not set" - ErrVersionNotSet common.ErrMsg = "version not set for certificate" - ErrInvalidSignAlgorithm common.ErrMsg = "invalid signature algorithm" - ErrInvalidEncAlgorithm common.ErrMsg = "invalid encryption algorithm" -) - -const ( - ASConfFileName = "as.ini" - KeyAlgSectionName = "Key Algorithms" - ASSectionName = "AS Certificate" - IssuerSectionName = "Issuer Certificate" -) - -var ( - defaultSignAlgorithm = scrypto.Ed25519 - defaultEncAlgorithm = scrypto.Curve25519xSalsa20Poly1305 - - validSignAlgorithms = []string{defaultSignAlgorithm} - validEncAlgorithms = []string{defaultEncAlgorithm} -) - -// ASCfg contains the as.ini configuration parameters. -type ASCfg struct { - *AS `ini:"AS Certificate"` - *Issuer `ini:"Issuer Certificate,omitempty"` - *PrimaryKeyAlgorithms `ini:"Key Algorithms,omitempty"` -} - -// NewTemplateASCfg creates a new template AS configuration. -func NewTemplateASCfg(subject addr.IA, trcVer uint64, voting, issuing bool) *ASCfg { - a := &ASCfg{} - a.AS = &AS{ - BaseCert: &BaseCert{ - Version: 1, - Description: "AS certificate", - Validity: 24 * 3 * time.Hour, - }, - EncAlgorithm: defaultEncAlgorithm, - SignAlgorithm: defaultSignAlgorithm, - IssuerIA: addr.IA{}, - IssuerCertVersion: 1, - } - if issuing { - a.Issuer = &Issuer{ - BaseCert: &BaseCert{ - Version: 1, - Description: "Issuer certificate", - Validity: 24 * 7 * time.Hour, - }, - IssuingAlgorithm: defaultSignAlgorithm, - TRCVersion: trcVer, - } - a.AS.IssuerIA = subject - } - if issuing || voting { - a.PrimaryKeyAlgorithms = &PrimaryKeyAlgorithms{} - if issuing { - a.PrimaryKeyAlgorithms.Issuing = defaultSignAlgorithm - } - if voting { - a.PrimaryKeyAlgorithms.Online = defaultSignAlgorithm - a.PrimaryKeyAlgorithms.Offline = defaultSignAlgorithm - } - } - return a -} - -// LoadASCfg loads the AS configuration from a directory. -func LoadASCfg(dir string) (*ASCfg, error) { - cfg, err := ini.Load(ASCfgPath(dir)) - if err != nil { - return nil, err - } - as := &ASCfg{} - if err := cfg.MapTo(as); err != nil { - return nil, err - } - if err := as.Validate(); err != nil { - return nil, err - } - return as, nil -} - -// ASCfgPath returns the path to the AS config file given a directory. -func ASCfgPath(dir string) string { - return filepath.Join(dir, ASConfFileName) -} - -// Validate parses the raw values and validates that the AS config is correct. -func (a *ASCfg) Validate() error { - if a.AS == nil { - return common.NewBasicError(ErrASCertMissing, nil) - } - if err := a.AS.validate(); err != nil { - return err - } - if err := a.Issuer.validate(); err != nil { - return err - } - if a.PrimaryKeyAlgorithms != nil { - return a.PrimaryKeyAlgorithms.validate() - } - return nil -} - -// Write writes the AS config to the provided path. -func (a *ASCfg) Write(path string, force bool) error { - // Check if file exists and do not override without -f - if !force { - // Check if the file already exists. - if _, err := os.Stat(path); err == nil { - pkicmn.QuietPrint("%s already exists. Use -f to overwrite.\n", path) - return nil - } - } - a.Update() - iniCfg := ini.Empty() - if err := iniCfg.ReflectFrom(a); err != nil { - return err - } - if err := iniCfg.SaveTo(path); err != nil { - return err - } - pkicmn.QuietPrint("Successfully written %s\n", path) - return nil -} - -// Update sets the raw values from the set values. -func (a *ASCfg) Update() { - a.AS.set() - if a.Issuer != nil { - a.Issuer.set() - } -} - -// AS corresponds to the "As Certificate" section. -type AS struct { - *BaseCert `ini:"AS Certificate"` - EncAlgorithm string `comment:"Encryption algorithm used by AS, e.g., curve25519xsalsa20poly1305"` - SignAlgorithm string `comment:"Signing algorithm used by AS, e.g., ed25519"` - RawIssuerIA string `ini:"IssuerIA" comment:"The issuer IA."` - IssuerIA addr.IA `ini:"-"` - IssuerCertVersion uint64 `comment:"The certificate version of the issuer certificate"` -} - -func (c *AS) validate() error { - if err := defaultAndValidateEncAlgorithm(&c.EncAlgorithm); err != nil { - return err - } - if err := defaultAndValidateSignAlgorithm(&c.SignAlgorithm); err != nil { - return common.NewBasicError("invalid SignAlgorithm", err) - } - if c.RawIssuerIA == "" { - return common.NewBasicError(ErrIssuerMissing, nil) - } - var err error - c.IssuerIA, err = addr.IAFromString(c.RawIssuerIA) - if err != nil || c.IssuerIA.IsWildcard() { - return common.NewBasicError(ErrInvalidIssuer, err, "ia", c.RawIssuerIA) - } - if c.IssuerCertVersion == 0 { - return common.NewBasicError(ErrInvalidIssuerCertVersion, nil) - } - if err := c.BaseCert.validate(); err != nil { - return err - } - return nil -} - -func (c *AS) set() { - c.RawIssuerIA = c.IssuerIA.String() - c.BaseCert.set() -} - -// Issuer corresponds to the "Issuer Certificate" section. -type Issuer struct { - *BaseCert `ini:"Issuer Certificate"` - IssuingAlgorithm string `comment:"Issuing algorithm used by AS, e.g., ed25519"` - TRCVersion uint64 `comment:"The version of the current TRC"` -} - -func (c *Issuer) validate() error { - if c.isZero() { - return nil - } - if err := defaultAndValidateSignAlgorithm(&c.IssuingAlgorithm); err != nil { - return common.NewBasicError("invalid IssuingAlgorithm", err) - } - if c.TRCVersion == 0 { - return common.NewBasicError(ErrInvalidIssuerTRCVersion, nil) - } - if err := c.BaseCert.validate(); err != nil { - return err - } - return nil - -} - -func (c *Issuer) isZero() bool { - return c == nil || *c == Issuer{} -} - -// BaseCert holds the shared parameters that are used to create certs. -type BaseCert struct { - Version uint64 `comment:"The version of the certificate. Cannot be 0"` - Description string `comment:"Description of the AS and certificate"` - OptionalDistributionPoints []addr.IA `ini:"-"` - RawOptDistPoints []string `ini:"OptionalDistributionPoints" comment:"List of optional revocation distribution points."` - NotBefore uint32 `comment:"Time of issuance as UNIX epoch. If 0 will be set to now."` - Validity time.Duration `ini:"-"` - RawValidity string `ini:"Validity" comment:"The validity of the certificate as duration string, e.g., 180d or 36h"` - RevAlgorithm string `comment:"Revocation algorithm used by AS, e.g., ed25519. If empty, no revocation key is generated."` -} - -func (c *BaseCert) validate() error { - if c.Version == 0 { - return common.NewBasicError(ErrVersionNotSet, nil) - } - for _, raw := range c.RawOptDistPoints { - ia, err := addr.IAFromString(raw) - if err != nil || ia.IsWildcard() { - return common.NewBasicError(ErrInvalidOptDistPoint, nil, "ia", ia) - } - c.OptionalDistributionPoints = append(c.OptionalDistributionPoints, ia) - } - if err := parseValidity(&c.NotBefore, &c.Validity, c.RawValidity); err != nil { - return err - } - if c.RevAlgorithm != "" { - if err := defaultAndValidateSignAlgorithm(&c.RevAlgorithm); err != nil { - return common.NewBasicError("invalid RevAlgorithm", err) - } - } - return nil -} - -func (c *BaseCert) set() { - c.RawOptDistPoints = nil - for _, ia := range c.OptionalDistributionPoints { - c.RawOptDistPoints = append(c.RawOptDistPoints, ia.String()) - } - c.RawValidity = util.FmtDuration(c.Validity) -} - -// PrimaryKeyAlgorithms holds the algorithms for the keys for a primary AS. -type PrimaryKeyAlgorithms struct { - Online string `ini:"Online,omitempty" comment:"Signing algorithm used by Online Key, e.g., ed25519"` - Offline string `ini:"Offline,omitempty" comment:"Signing algorithm used by Offline Key, e.g., ed25519"` - Issuing string `ini:"Issuing,omitempty" comment:"Signing algorithm used by Issuing Key, e.g., ed25519"` -} - -func (k *PrimaryKeyAlgorithms) validate() error { - if err := defaultAndValidateSignAlgorithm(&k.Online); err != nil { - return err - } - if err := defaultAndValidateSignAlgorithm(&k.Offline); err != nil { - return err - } - if err := defaultAndValidateSignAlgorithm(&k.Issuing); err != nil { - return err - } - return nil -} - -func defaultAndValidateSignAlgorithm(algo *string) error { - if *algo == "" { - *algo = defaultSignAlgorithm - } - return validateAlgorithm(*algo, validSignAlgorithms, ErrInvalidSignAlgorithm) - -} - -func defaultAndValidateEncAlgorithm(algo *string) error { - if *algo == "" { - *algo = defaultEncAlgorithm - } - return validateAlgorithm(*algo, validEncAlgorithms, ErrInvalidEncAlgorithm) -} - -func validateAlgorithm(algorithm string, valid []string, errMsg common.ErrMsg) error { - for _, a := range valid { - if a == algorithm { - return nil - } - } - return common.NewBasicError(errMsg, nil, "algorithm", algorithm) -} - -func parseValidity(notBefore *uint32, validity *time.Duration, raw string) error { - if *notBefore == 0 { - *notBefore = util.TimeToSecs(time.Now()) - } - if raw == "" { - raw = "0s" - } - var err error - *validity, err = util.ParseDuration(raw) - if err != nil { - return common.NewBasicError(ErrInvalidValidityDuration, nil, "duration", raw) - } - if int64(*validity) == 0 { - return common.NewBasicError(ErrValidityDurationNotSet, nil) - } - return nil -} diff --git a/go/tools/scion-pki/internal/v2/conf/as_test.go b/go/tools/scion-pki/internal/v2/conf/as_test.go deleted file mode 100644 index 0ea6e40ff5..0000000000 --- a/go/tools/scion-pki/internal/v2/conf/as_test.go +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2019 Anapaya Systems -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package conf_test - -import ( - "testing" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/scrypto" - "github.com/scionproto/scion/go/lib/xtest" - "github.com/scionproto/scion/go/tools/scion-pki/internal/v2/conf" -) - -func TestAsValidate(t *testing.T) { - tests := map[string]struct { - Modify func(*conf.ASCfg) - ExpectedErrMsg error - }{ - "valid AS cert from template": { - Modify: func(cfg *conf.ASCfg) { - *cfg = *conf.NewTemplateASCfg(xtest.MustParseIA("1-ff00:0:110"), 4, true, true) - cfg.Update() - }, - }, - "valid AS cert from template with modifications": { - Modify: func(cfg *conf.ASCfg) { - *cfg = *conf.NewTemplateASCfg(xtest.MustParseIA("1-ff00:0:110"), 4, false, true) - cfg.AS.OptionalDistributionPoints = []addr.IA{xtest.MustParseIA("2-ff00:0:210")} - cfg.AS.EncAlgorithm = "" - cfg.AS.SignAlgorithm = "" - cfg.Update() - }, - }, - "valid AS cert": { - Modify: func(cfg *conf.ASCfg) { - cfg.Issuer = nil - cfg.PrimaryKeyAlgorithms = nil - }, - }, - "valid AS and issuer cert": { - Modify: func(cfg *conf.ASCfg) {}, - }, - "empty AS": { - Modify: func(cfg *conf.ASCfg) { - *cfg = conf.ASCfg{} - }, - ExpectedErrMsg: conf.ErrASCertMissing, - }, - "invalid optional distribution points": { - Modify: func(cfg *conf.ASCfg) { - cfg.AS.RawOptDistPoints = []string{"2-0"} - }, - ExpectedErrMsg: conf.ErrInvalidOptDistPoint, - }, - "empty Issuer inside AS Cert": { - Modify: func(cfg *conf.ASCfg) { - cfg.AS.RawIssuerIA = "" - }, - ExpectedErrMsg: conf.ErrIssuerMissing, - }, - "wildcard Issuer inside AS Cert": { - Modify: func(cfg *conf.ASCfg) { - cfg.AS.RawIssuerIA = "1-0" - }, - ExpectedErrMsg: conf.ErrInvalidIssuer, - }, - "invalid IssuerCertVersion": { - Modify: func(cfg *conf.ASCfg) { - cfg.AS.IssuerCertVersion = 0 - }, - ExpectedErrMsg: conf.ErrInvalidIssuerCertVersion, - }, - "invalid TRCVersion": { - Modify: func(cfg *conf.ASCfg) { - cfg.Issuer.TRCVersion = 0 - }, - ExpectedErrMsg: conf.ErrInvalidIssuerTRCVersion, - }, - "invalid Version": { - Modify: func(cfg *conf.ASCfg) { - cfg.AS.Version = 0 - }, - ExpectedErrMsg: conf.ErrVersionNotSet, - }, - "invalid RawValidity": { - Modify: func(cfg *conf.ASCfg) { - cfg.Issuer.RawValidity = "3" - }, - ExpectedErrMsg: conf.ErrInvalidValidityDuration, - }, - "zero validity": { - Modify: func(cfg *conf.ASCfg) { - cfg.AS.RawValidity = "" - }, - ExpectedErrMsg: conf.ErrValidityDurationNotSet, - }, - "invalid sign algorithm": { - Modify: func(cfg *conf.ASCfg) { - cfg.AS.SignAlgorithm = scrypto.Curve25519xSalsa20Poly1305 - }, - ExpectedErrMsg: conf.ErrInvalidSignAlgorithm, - }, - "invalid revocation algorithm": { - Modify: func(cfg *conf.ASCfg) { - cfg.AS.RevAlgorithm = scrypto.Curve25519xSalsa20Poly1305 - }, - ExpectedErrMsg: conf.ErrInvalidSignAlgorithm, - }, - "invalid issuing algorithm": { - Modify: func(cfg *conf.ASCfg) { - cfg.Issuer.IssuingAlgorithm = scrypto.Curve25519xSalsa20Poly1305 - }, - ExpectedErrMsg: conf.ErrInvalidSignAlgorithm, - }, - "invalid encryption algorithm": { - Modify: func(cfg *conf.ASCfg) { - cfg.AS.EncAlgorithm = scrypto.Ed25519 - }, - ExpectedErrMsg: conf.ErrInvalidEncAlgorithm, - }, - "invalid online key": { - Modify: func(cfg *conf.ASCfg) { - cfg.PrimaryKeyAlgorithms.Online = scrypto.Curve25519xSalsa20Poly1305 - }, - ExpectedErrMsg: conf.ErrInvalidSignAlgorithm, - }, - "invalid offline key": { - Modify: func(cfg *conf.ASCfg) { - cfg.PrimaryKeyAlgorithms.Offline = scrypto.Curve25519xSalsa20Poly1305 - }, - ExpectedErrMsg: conf.ErrInvalidSignAlgorithm, - }, - "invalid issuing key": { - Modify: func(cfg *conf.ASCfg) { - cfg.PrimaryKeyAlgorithms.Issuing = scrypto.Curve25519xSalsa20Poly1305 - }, - ExpectedErrMsg: conf.ErrInvalidSignAlgorithm, - }, - } - for name, test := range tests { - t.Run(name, func(t *testing.T) { - as := conf.ASCfg{ - AS: &conf.AS{ - BaseCert: &conf.BaseCert{ - Version: 1, - Description: "AS certificate", - RawOptDistPoints: []string{"2-ff00:0:210"}, - NotBefore: 0, - RawValidity: "3d", - RevAlgorithm: scrypto.Ed25519, - }, - EncAlgorithm: scrypto.Curve25519xSalsa20Poly1305, - SignAlgorithm: scrypto.Ed25519, - RawIssuerIA: "1-ff00:0:110", - IssuerCertVersion: 2, - }, - Issuer: &conf.Issuer{ - BaseCert: &conf.BaseCert{ - Version: 2, - Description: "Issuer certificate", - RawOptDistPoints: []string{"2-ff00:0:210"}, - NotBefore: 0, - RawValidity: "7d", - RevAlgorithm: scrypto.Ed25519, - }, - IssuingAlgorithm: scrypto.Ed25519, - TRCVersion: 4, - }, - PrimaryKeyAlgorithms: &conf.PrimaryKeyAlgorithms{ - Online: scrypto.Ed25519, - Offline: scrypto.Ed25519, - Issuing: scrypto.Ed25519, - }, - } - test.Modify(&as) - err := as.Validate() - xtest.AssertErrorsIs(t, err, test.ExpectedErrMsg) - }) - } -} diff --git a/go/tools/scion-pki/internal/v2/conf/isd.go b/go/tools/scion-pki/internal/v2/conf/isd.go deleted file mode 100644 index 67106e352f..0000000000 --- a/go/tools/scion-pki/internal/v2/conf/isd.go +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2018 ETH Zurich, Anapaya Systems -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package conf - -import ( - "os" - "path/filepath" - "time" - - "github.com/go-ini/ini" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/common" - "github.com/scionproto/scion/go/lib/serrors" - "github.com/scionproto/scion/go/lib/util" - "github.com/scionproto/scion/go/tools/scion-pki/internal/pkicmn" -) - -const ISDCfgFileName = "isd.ini" - -const ( - ErrAuthoritativeNotCore common.ErrMsg = "authoritative must be core" - ErrInvalidGracePeriod common.ErrMsg = "invalid GracePeriod duration" - ErrVotingQuorumGreaterThanVotingASes common.ErrMsg = "VotingQuorun > # Voting ASes" - ErrVotingQuorumNotSet common.ErrMsg = "VotingQuorum not set" - ErrTrcVersionNotSet common.ErrMsg = "Version not set for TRC" -) - -// ISDCfg holds config parameters read from isd.ini. -type ISDCfg struct { - Desc string `comment:"General description for the ISD"` - *TRC `ini:"TRC"` -} - -// NewTemplateISDCfg creates a new template ISD configuration. -func NewTemplateISDCfg() *ISDCfg { - i := &ISDCfg{ - TRC: &TRC{ - Version: 1, - BaseVersion: 1, - Validity: 180 * 24 * time.Hour, - TrustResetAllowed: true, - }, - } - return i -} - -// LoadISDCfg loads the ISD configuration from a directory. -func LoadISDCfg(dir string) (*ISDCfg, error) { - cfg, err := ini.Load(ISDCfgPath(dir)) - if err != nil { - return nil, err - } - i := &ISDCfg{} - if err = cfg.MapTo(i); err != nil { - return nil, err - } - if len(i.Desc) == 0 { - return nil, serrors.New("description not set") - } - if err = i.TRC.Validate(); err != nil { - return nil, err - } - return i, nil -} - -// ISDCfgPath returns the path to the ISD config file given a directory. -func ISDCfgPath(dir string) string { - return filepath.Join(dir, ISDCfgFileName) -} - -// Write writes the ISD config to the provided path. -func (i *ISDCfg) Write(path string, force bool) error { - // Check if file exists and do not override without -f - if !force { - if _, err := os.Stat(path); err == nil { - pkicmn.QuietPrint("%s already exists. Use -f to overwrite.\n", path) - return nil - } - } - i.Update() - iniCfg := ini.Empty() - if err := ini.ReflectFrom(iniCfg, i); err != nil { - return err - } - if err := iniCfg.SaveTo(path); err != nil { - return err - } - pkicmn.QuietPrint("Successfully written %s\n", path) - return nil -} - -// TRC holds the parameters that are used to generate a TRC. -type TRC struct { - Version uint64 `comment:"The version of the TRC. Must not be 0."` - BaseVersion uint64 `comment:"The base version of the TRC. Must not be 0."` - VotingQuorum int `comment:"The number of voting ASes needed to update the TRC"` - GracePeriod time.Duration `ini:"-"` - RawGracePeriod string `ini:"GracePeriod" comment:"The grace period for the previous TRC as duration string, e.g., 30m or 6h"` - TrustResetAllowed bool `comment:"Whether trust resets are allowed for this ISD"` - NotBefore uint32 `comment:"Time of issuance as UNIX epoch. If 0 will be set to now."` - Validity time.Duration `ini:"-"` - RawValidity string `ini:"Validity" comment:"The validity of the certificate as duration string, e.g., 180d or 36h."` - AuthoritativeASes []addr.AS `ini:"-"` - CoreASes []addr.AS `ini:"-"` - IssuingASes []addr.AS `ini:"-"` - VotingASes []addr.AS `ini:"-"` - RawAuthoritativeASes []string `ini:"AuthoritativeASes" comment:"The authoritative ASes of this ISD as comma-separated list, e.g., ff00:0:110,ff00:0:120"` - RawCoreASes []string `ini:"CoreASes" comment:"The core ASes of this ISD as comma-separated list, e.g., ff00:0:110,ff00:0:120"` - RawIssuingASes []string `ini:"IssuingASes" comment:"The issuing ASes of this ISD as comma-separated list, e.g., ff00:0:110,ff00:0:120"` - RawVotingASes []string `ini:"VotingASes" comment:"The voting ASes of this ISD as comma-separated list, e.g., ff00:0:110,ff00:0:120"` -} - -// Update sets the raw values from the set values. -func (t *TRC) Update() { - // Make sure raw primaries and parsed primaries are in sync. - t.setPrimaries() - // Make sure RawValidity and Validity are in sync. - t.RawValidity = util.FmtDuration(t.Validity) - t.RawGracePeriod = util.FmtDuration(t.GracePeriod) -} - -func (t *TRC) setPrimaries() { - t.RawAuthoritativeASes = t.rawASes(t.AuthoritativeASes) - t.RawCoreASes = t.rawASes(t.CoreASes) - t.RawIssuingASes = t.rawASes(t.IssuingASes) - t.RawVotingASes = t.rawASes(t.VotingASes) -} - -func (t *TRC) rawASes(ases []addr.AS) []string { - var raw []string - for _, as := range ases { - raw = append(raw, as.String()) - } - return raw -} - -// Validate parses the raw values and validates that the TRC config is correct. -func (t *TRC) Validate() error { - if err := t.parsePrimaries(); err != nil { - return err - } - if err := t.checkValuesSet(); err != nil { - return err - } - if err := t.checkInvariant(); err != nil { - return err - } - return nil -} - -func (t *TRC) parsePrimaries() error { - var err error - if t.AuthoritativeASes, err = t.parsePrimary(t.RawAuthoritativeASes); err != nil { - return common.NewBasicError("invalid AuthoritativeASes", err) - } - if t.CoreASes, err = t.parsePrimary(t.RawCoreASes); err != nil { - return common.NewBasicError("invalid CoreASes", err) - } - if t.IssuingASes, err = t.parsePrimary(t.RawIssuingASes); err != nil { - return common.NewBasicError("invalid IssuingASes", err) - } - if t.VotingASes, err = t.parsePrimary(t.RawVotingASes); err != nil { - return common.NewBasicError("invalid VotingASes", err) - } - return nil -} - -func (t *TRC) parsePrimary(raw []string) ([]addr.AS, error) { - var ases []addr.AS - if len(raw) == 0 { - return nil, serrors.New("section not set") - } - for _, raw := range raw { - as, err := addr.ASFromString(raw) - if err != nil { - return nil, err - } - if as == 0 { - return nil, common.NewBasicError("invalid AS", nil, "as", as) - } - ases = append(ases, as) - } - return ases, nil -} - -func (t *TRC) checkValuesSet() error { - if t.Version == 0 { - return common.NewBasicError(ErrTrcVersionNotSet, nil) - } - if t.BaseVersion != t.Version { - return serrors.New("only base TRCs supported currently") - } - if t.VotingQuorum == 0 { - return common.NewBasicError(ErrVotingQuorumNotSet, nil) - } - if t.RawGracePeriod == "" { - t.RawGracePeriod = "0s" - } - var err error - t.GracePeriod, err = util.ParseDuration(t.RawGracePeriod) - if err != nil { - return common.NewBasicError(ErrInvalidGracePeriod, nil, "duration", t.RawGracePeriod) - } - if err := parseValidity(&t.NotBefore, &t.Validity, t.RawValidity); err != nil { - return err - } - return nil -} - -func (t *TRC) checkInvariant() error { - if int(t.VotingQuorum) > len(t.VotingASes) { - return common.NewBasicError(ErrVotingQuorumGreaterThanVotingASes, nil, - "quorum", t.VotingQuorum, "voting", t.VotingASes) - } - for _, as := range t.AuthoritativeASes { - if !pkicmn.ContainsAS(t.CoreASes, as) { - return common.NewBasicError(ErrAuthoritativeNotCore, nil, "as", as) - } - } - if t.Version == t.BaseVersion && t.GracePeriod != 0 { - return common.NewBasicError(ErrInvalidGracePeriod, nil, - "reason", "must be zero for base TRC") - } - if t.Version != t.BaseVersion && t.GracePeriod == 0 { - return common.NewBasicError(ErrInvalidGracePeriod, nil, - "reason", "must not be zero for non-base TRC") - } - return nil -} diff --git a/go/tools/scion-pki/internal/v2/conf/isd_test.go b/go/tools/scion-pki/internal/v2/conf/isd_test.go deleted file mode 100644 index 3645b145d5..0000000000 --- a/go/tools/scion-pki/internal/v2/conf/isd_test.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2019 Anapaya Systems -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package conf_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/xtest" - "github.com/scionproto/scion/go/tools/scion-pki/internal/v2/conf" -) - -var ( - as110 = xtest.MustParseAS("ff00:0:110") - as120 = xtest.MustParseAS("ff00:0:120") - as130 = xtest.MustParseAS("ff00:0:130") - as140 = xtest.MustParseAS("ff00:0:140") - as150 = xtest.MustParseAS("ff00:0:150") - - authoritative = []addr.AS{as110, as120} - core = []addr.AS{as110, as120, as130} - issuing = []addr.AS{as140, as150} - voting = []addr.AS{as110, as130, as140} -) - -func TestValidatingTrc(t *testing.T) { - tests := map[string]struct { - Modify func(trc *conf.TRC) - ExpectedErrMsg string - }{ - "valid": { - Modify: func(trc *conf.TRC) {}, - }, - "template TRC": { - Modify: func(trc *conf.TRC) { - *trc = *conf.NewTemplateISDCfg().TRC - trc.AuthoritativeASes = authoritative - trc.CoreASes = core - trc.IssuingASes = issuing - trc.VotingASes = voting - trc.VotingQuorum = 2 - trc.Update() - }, - }, - "Version not set": { - Modify: func(trc *conf.TRC) { - trc.Version = 0 - }, - ExpectedErrMsg: conf.ErrTrcVersionNotSet.Error(), - }, - "invalid validity duration": { - Modify: func(trc *conf.TRC) { - trc.RawValidity = "18" - }, - ExpectedErrMsg: conf.ErrInvalidValidityDuration.Error(), - }, - "authoritative not set": { - Modify: func(trc *conf.TRC) { - trc.RawAuthoritativeASes = []string{} - }, - ExpectedErrMsg: "invalid AuthoritativeASes", - }, - "core not set": { - Modify: func(trc *conf.TRC) { - trc.RawCoreASes = []string{} - }, - ExpectedErrMsg: "invalid CoreASes", - }, - "issuing not set": { - Modify: func(trc *conf.TRC) { - trc.RawIssuingASes = []string{} - }, - ExpectedErrMsg: "invalid IssuingASes", - }, - "voting not set": { - Modify: func(trc *conf.TRC) { - trc.RawVotingASes = []string{} - }, - ExpectedErrMsg: "invalid VotingASes", - }, - "malformed voting AS": { - Modify: func(trc *conf.TRC) { - trc.RawVotingASes = append(trc.RawVotingASes, "1-0") - }, - ExpectedErrMsg: "Unable to parse AS", - }, - "invalid voting AS": { - Modify: func(trc *conf.TRC) { - trc.RawVotingASes = append(trc.RawVotingASes, "0") - }, - ExpectedErrMsg: "invalid AS", - }, - "authoritative but not core AS": { - Modify: func(trc *conf.TRC) { - trc.RawCoreASes = trc.RawCoreASes[:len(trc.RawCoreASes)-2] - }, - ExpectedErrMsg: conf.ErrAuthoritativeNotCore.Error(), - }, - "VotingQuorum not set": { - Modify: func(trc *conf.TRC) { - trc.VotingQuorum = 0 - }, - ExpectedErrMsg: conf.ErrVotingQuorumNotSet.Error(), - }, - "invalid GracePeriod": { - Modify: func(trc *conf.TRC) { - trc.RawGracePeriod = "18" - }, - ExpectedErrMsg: conf.ErrInvalidGracePeriod.Error(), - }, - "base and non-zero GracePeriod": { - Modify: func(trc *conf.TRC) { - trc.RawGracePeriod = "6h" - }, - ExpectedErrMsg: conf.ErrInvalidGracePeriod.Error(), - }, - "VotingQuorum greater than number of voting ASes": { - Modify: func(trc *conf.TRC) { - trc.VotingQuorum = len(trc.RawVotingASes) + 1 - }, - ExpectedErrMsg: conf.ErrVotingQuorumGreaterThanVotingASes.Error(), - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - trc := conf.TRC{ - Version: 1, - BaseVersion: 1, - VotingQuorum: 2, - TrustResetAllowed: true, - NotBefore: 0, - RawValidity: "180d", - RawAuthoritativeASes: toRawASes(authoritative), - RawCoreASes: toRawASes(core), - RawIssuingASes: toRawASes(issuing), - RawVotingASes: toRawASes(voting), - } - test.Modify(&trc) - err := trc.Validate() - if test.ExpectedErrMsg == "" { - require.NoError(t, err) - } else { - require.Error(t, err) - assert.Contains(t, err.Error(), test.ExpectedErrMsg) - } - }) - } -} - -func toRawASes(ases []addr.AS) []string { - raw := make([]string, 0, len(ases)) - for _, as := range ases { - raw = append(raw, as.String()) - } - return raw -}