diff --git a/go/lib/infra/modules/trust/internal/metrics/metrics.go b/go/lib/infra/modules/trust/internal/metrics/metrics.go index 7f2c14534d..e414ae21f5 100644 --- a/go/lib/infra/modules/trust/internal/metrics/metrics.go +++ b/go/lib/infra/modules/trust/internal/metrics/metrics.go @@ -41,15 +41,16 @@ const ( OkExists = "ok_exists" OkInserted = "ok_inserted" - ErrDB = prom.ErrDB - ErrDenied = "err_denied" - ErrInternal = prom.ErrInternal - ErrTransmit = "err_transmit" - ErrTimeout = prom.ErrTimeout - ErrValidate = prom.ErrValidate - ErrVerify = prom.ErrVerify - ErrTRC = "err_trc" - ErrNotFound = "err_not_found" + ErrDB = prom.ErrDB + ErrDenied = "err_denied" + ErrInternal = prom.ErrInternal + ErrTransmit = "err_transmit" + ErrTimeout = prom.ErrTimeout + ErrValidate = prom.ErrValidate + ErrVerify = prom.ErrVerify + ErrTRC = "err_trc" + ErrNotFound = "err_not_found" + ErrNotFoundAuth = "err_not_found_auth" ) var ( diff --git a/go/lib/infra/modules/trust/trust.go b/go/lib/infra/modules/trust/trust.go index 18fca45e65..430a8be1e9 100644 --- a/go/lib/infra/modules/trust/trust.go +++ b/go/lib/infra/modules/trust/trust.go @@ -216,6 +216,16 @@ func (store *Store) getTRC(ctx context.Context, isd addr.ISD, version scrypto.Ve metrics.Store.Lookup(l.WithResult(metrics.OkCached)).Inc() return trcObj, nil } + if store.config.ServiceType == proto.ServiceType_cs && + store.config.TopoProvider.Get().Core && store.ia.I == isd { + // Core CS can't find TRC for its own ISD + + metrics.Store.Lookup(l.WithResult(metrics.ErrNotFoundAuth)).Inc() + // XXX(kormat): Wrap ErrMissingAuthoritative with ErrNotFoundLocally to + // simplify logic in LoadAuthoritativeTRC + return nil, serrors.Wrap(ErrMissingAuthoritative, ErrNotFoundLocally, + "isd", isd, "version", version, "client", client) + } if opts.LocalOnly { metrics.Store.Lookup(l.WithResult(metrics.ErrNotFound)).Inc() return nil, serrors.WithCtx(ErrNotFoundLocally, "isd", isd, "version", version, @@ -364,9 +374,21 @@ func (store *Store) getChain(ctx context.Context, ia addr.IA, version scrypto.Ve metrics.Store.Lookup(l.WithResult(metrics.OkCached)).Inc() return chain, nil } - if store.config.MustHaveLocalChain && store.ia.Equal(ia) { - metrics.Store.Lookup(l).Inc() - return nil, serrors.WithCtx(ErrMissingAuthoritative, "requested_ia", ia) + isCS := store.config.ServiceType == proto.ServiceType_cs + isCore := store.config.TopoProvider.Get().Core + if (isCS && store.ia.Equal(ia)) || + (isCS && isCore && store.ia.I == ia.I) || + (store.config.MustHaveLocalChain && store.ia.Equal(ia) && version.IsLatest()) { + // Either: + // - CS can't find a cert for its own AS + // or + // - Core CS can't find cert for AS in own ISD + // or + // - Infra service doesn't have any version of its own cert + + metrics.Store.Lookup(l.WithResult(metrics.ErrNotFoundAuth)).Inc() + return nil, serrors.WithCtx(ErrMissingAuthoritative, "ia", ia, "version", version, + "client", client) } // Chain not found, so we'll need to fetch one. First, fetch the TRC we'll // need during certificate chain validation. @@ -380,7 +402,8 @@ func (store *Store) getChain(ctx context.Context, ia addr.IA, version scrypto.Ve } if opts.LocalOnly { metrics.Store.Lookup(l.WithResult(metrics.ErrNotFound)).Inc() - return nil, serrors.WithCtx(ErrNotFoundLocally, "ia", ia) + return nil, serrors.WithCtx(ErrNotFoundLocally, "ia", ia, "version", version, + "client", client) } if opts.Server == nil { var err error diff --git a/go/lib/scrypto/version.go b/go/lib/scrypto/version.go index 6d3d5ee558..30fac9029c 100644 --- a/go/lib/scrypto/version.go +++ b/go/lib/scrypto/version.go @@ -30,6 +30,11 @@ var _ json.Marshaler = (*Version)(nil) // marshalled/unmarshalled to/from LatestVer. type Version uint64 +// IsLatest checks if the value is LatestVer +func (v Version) IsLatest() bool { + return uint64(v) == LatestVer +} + // UnmarshalJSON checks that the value is not LatestVer. func (v *Version) UnmarshalJSON(b []byte) error { parsed, err := strconv.ParseUint(string(b), 10, 64)